diff --git a/CHANGES b/CHANGES
index 3fc4dcc4f49513c80e100d9114c2972c6055e98f..7e4abc3136457fbad8a76b9777f7425ee6cf0a62 100755
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,4 @@
+ -- Add experimental "trunk" option to IAX2 for high density VoIP
  -- Add experimental "debug channel" command
  -- Add 'C' flag to dial command to reset call detail record (handy for calling cards)
  -- Add NAT and dynamic support to MGCP
diff --git a/apps/Makefile b/apps/Makefile
index 48087f76c6690892569a33309212aaf924a7c3e5..30e1a9f273bb733ff7b2d10317d417438357d54c 100755
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -19,7 +19,7 @@ APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_intercom.
      app_queue.so app_senddtmf.so app_parkandannounce.so app_striplsd.so \
      app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \
      app_authenticate.so app_softhangup.so app_lookupblacklist.so \
-     app_waitforring.so app_privacy.so app_db.so
+     app_waitforring.so app_privacy.so app_db.so app_chanisavail.so
 
 #APPS+=app_sql_postgres.so
 #APPS+=app_sql_odbc.so
diff --git a/apps/app_chanisavail.c b/apps/app_chanisavail.c
new file mode 100755
index 0000000000000000000000000000000000000000..e2ad6e7e9a95526f791c3a10ca9e931921a1d04c
--- /dev/null
+++ b/apps/app_chanisavail.c
@@ -0,0 +1,130 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Check if Channel is Available
+ * 
+ * Copyright (C) 2003, Digium
+ *
+ * Mark Spencer <markster@digium.com>
+ * James Golovich <james@gnuinter.net>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ *
+ */
+
+#include <asterisk/lock.h>
+#include <asterisk/file.h>
+#include <asterisk/logger.h>
+#include <asterisk/channel.h>
+#include <asterisk/pbx.h>
+#include <asterisk/module.h>
+#include <asterisk/app.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+
+#include <pthread.h>
+
+static char *tdesc = "Check if channel is available";
+
+static char *app = "ChanIsAvail";
+
+static char *synopsis = "Check if channel is available";
+
+static char *descrip = 
+"  ChanIsAvail(Technology/resource[&Technology2/resource2...]): \n"
+"Checks is any of the requested channels are available.  If none\n"
+"of the requested channels are available the new priority will\n"
+"be n+101 (unless such a priority does not exist, in which case\n"
+"ChanIsAvail will return -1.  If any of the requested channels\n"
+"are available, the next priority will be n+1 and ChanIsAvail\n"
+"will return 0.\n";
+
+STANDARD_LOCAL_USER;
+
+LOCAL_USER_DECL;
+
+static int chanavail_exec(struct ast_channel *chan, void *data)
+{
+	int res=-1;
+	struct localuser *u;
+	char info[256], *peers, *tech, *number, *rest, *cur;
+	struct ast_channel *tempchan;
+
+	if (!data) {
+		ast_log(LOG_WARNING, "ChanIsAvail requires an argument (Zap/1&Zap/2)\n");
+		return -1;
+	}
+	LOCAL_USER_ADD(u);
+
+	strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
+	peers = info;
+	if (peers) {
+		cur = peers;
+		do {
+			/* remember where to start next time */
+			rest = strchr(cur, '&');
+			if (rest) {
+				*rest = 0;
+				rest++;
+			}
+			tech = cur;
+			number = strchr(tech, '/');
+			if (!number) {
+				ast_log(LOG_WARNING, "ChanIsAvail argument takes format (Zap/[device])\n");
+				continue;
+			}
+			*number = '\0';
+			number++;
+			if ((tempchan = ast_request(tech, chan->nativeformats, number))) {
+					ast_hangup(tempchan);
+					tempchan = NULL;
+					res = 1;
+					break;
+			}
+			cur = rest;
+		} while (cur);
+	}
+
+	if (res < 1) {
+		if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
+			chan->priority+=100;
+		else
+			return -1;
+	}
+
+	LOCAL_USER_REMOVE(u);
+	return 0;
+}
+
+int unload_module(void)
+{
+	STANDARD_HANGUP_LOCALUSERS;
+	return ast_unregister_application(app);
+}
+
+int load_module(void)
+{
+	return ast_register_application(app, chanavail_exec, synopsis, descrip);
+}
+
+char *description(void)
+{
+	return tdesc;
+}
+
+int usecount(void)
+{
+	int res;
+	STANDARD_USECOUNT(res);
+	return res;
+}
+
+char *key()
+{
+	return ASTERISK_GPL_KEY;
+}
diff --git a/astman/astman.c b/astman/astman.c
index 6fa6b811821e7369102010af4d3e2e0eb314c5ea..2eb35f68e5ba85cfb3a5442ddbec4a5cd3d3e078 100755
--- a/astman/astman.c
+++ b/astman/astman.c
@@ -383,14 +383,14 @@ static int show_doing(char *title, char *tmp)
 	return 0;
 }
 
-static int hide_doing()
+static int hide_doing(void)
 {
 	newtPopWindow();
 	newtFormDestroy(showform);
 	return 0;
 }
 
-static void try_status()
+static void try_status(void)
 {
 	struct message *m;
 	manager_action("Status", "");
diff --git a/channels/Makefile b/channels/Makefile
index 8105e7821133b05bdd212592edb369d9781c05f5..9bf327b6b48be5cbfdf080d2e8dd618f161410fb 100755
--- a/channels/Makefile
+++ b/channels/Makefile
@@ -33,6 +33,7 @@ ZAPPRI=$(shell [ -f /usr/lib/libpri.so.1 ] && echo "-lpri")
 ZAPR2=$(shell [ -f /usr/lib/libmfcr2.so.1 ] && echo "-lmfcr2")
 CHANZAP=$(shell if [ -f .oldzap ]; then echo "chan_zap_old.c"; else echo "chan_zap.c"; fi)
 ZAPLIB=$(shell if [ -f .oldzap ]; then echo "-lzap"; fi)
+CFLAGS+=$(shell [ -f /usr/include/linux/zaptel.h ] && echo "-DIAX_TRUNKING")
 
 ALSA_SRC=chan_alsa.c
 ALSA_SRC+=$(shell [ -f alsa-monitor.h ] && echo "alsa-monitor.h")
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index bd88107207c5e7fd9ef9fc2bd36c5757b5d4121c..e73f680b9c42b991a96dc682ed6f439de52d63c9 100755
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -44,6 +44,10 @@
 #include <unistd.h>
 #include <netdb.h>
 #include <fcntl.h>
+#ifdef IAX_TRUNKING
+#include <sys/ioctl.h>
+#include <linux/zaptel.h>
+#endif
 
 #include "iax2.h"
 
@@ -59,9 +63,14 @@
 #define DEFAULT_RETRY_TIME 1000
 #define MEMORY_SIZE 100
 #define DEFAULT_DROP 3
+/* Flag to use with trunk calls, keeping these calls high up.  It halves our effective use
+   but keeps the division between trunked and non-trunked better. */
+#define TRUNK_CALL_START	0x4000
 
 #define DEBUG_SUPPORT
 
+#define MIN_REUSE_TIME		60	/* Don't reuse a call number within 60 seconds */
+
 /* Sample over last 100 units to determine historic jitter */
 #define GAMMA (0.01)
 
@@ -74,8 +83,10 @@ static char context[80] = "default";
 static int max_retries = 4;
 static int ping_time = 20;
 static int lagrq_time = 10;
-static int nextcallno = 1;
+static int maxtrunkcall = TRUNK_CALL_START;
+static int maxnontrunkcall = 1;
 static int maxjitterbuffer=3000;
+static int trunkfreq = 20;
 
 static int iaxdefaultdpcache=10 * 60;	/* Cache dialplan entries for 10 minutes by default */
 
@@ -87,6 +98,8 @@ static int tos = 0;
 
 static int expirey = AST_DEFAULT_REG_EXPIRE;
 
+static int timingfd = -1;				/* Timing file descriptor */
+
 static int usecnt;
 static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
 
@@ -145,7 +158,7 @@ struct iax2_user {
 	char inkeys[80];				/* Key(s) this user can use to authenticate to us */
 	int amaflags;
 	int hascallerid;
-	int trunk;						/* Treat with IAX2 trunking */
+	int trunk;
 	char callerid[AST_MAX_EXTENSION];
 	struct ast_ha *ha;
 	struct iax2_context *contexts;
@@ -180,6 +193,10 @@ struct iax2_peer {
 	int capability;					/* Capability */
 	int delme;						/* I need to be deleted */
 	int trunk;						/* Treat as an IAX trunking */
+	struct timeval txtrunktime;		/* Transmit trunktime */
+	struct timeval rxtrunktime;		/* Receive trunktime */
+	struct timeval lasttxtime;		/* Last transmitted trunktime */
+	unsigned int lastsent;			/* Last sent time */
 
 	/* Qualification */
 	int callno;					/* Call number of POKE request */
@@ -350,6 +367,7 @@ struct chan_iax2_pvt {
 	/* Trunk data and length */
 	unsigned char trunkdata[MAX_TRUNKDATA];
 	unsigned int trunkdatalen;
+	int trunkerror;
 	struct iax2_dpcache *dpentries;
 };
 
@@ -538,7 +556,7 @@ static struct iax2_ie {
 	{ IAX_IE_VERSION, "VERSION", dump_short },
 	{ IAX_IE_ADSICPE, "ADSICPE", dump_short },
 	{ IAX_IE_DNID, "DNID", dump_string },
-	{ IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_int },
+	{ IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_short },
 	{ IAX_IE_CHALLENGE, "CHALLENGE", dump_string },
 	{ IAX_IE_MD5_RESULT, "MD5 RESULT", dump_string },
 	{ IAX_IE_RSA_RESULT, "RSA RESULT", dump_string },
@@ -719,6 +737,8 @@ void showframe(struct ast_iax2_frame *f, struct ast_iax2_full_hdr *fhi, int rx,
 /* XXX We probably should use a mutex when working with this XXX */
 static struct chan_iax2_pvt *iaxs[AST_IAX2_MAX_CALLS];
 static pthread_mutex_t iaxsl[AST_IAX2_MAX_CALLS];
+static struct timeval lastused[AST_IAX2_MAX_CALLS];
+
 
 static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
 static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
@@ -932,14 +952,99 @@ static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short
 	return 0;
 }
 
+static void update_max_trunk(void)
+{
+	int max = TRUNK_CALL_START;
+	int x;
+	/* XXX Prolly don't need locks here XXX */
+	for (x=TRUNK_CALL_START;x<AST_IAX2_MAX_CALLS - 1; x++) {
+		if (iaxs[x])
+			max = x + 1;
+	}
+	maxtrunkcall = max;
+	if (option_debug)
+		ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max);
+}
+
+static void update_max_nontrunk(void)
+{
+	int max = 1;
+	int x;
+	/* XXX Prolly don't need locks here XXX */
+	for (x=1;x<TRUNK_CALL_START - 1; x++) {
+		if (iaxs[x])
+			max = x + 1;
+	}
+	maxnontrunkcall = max;
+	if (option_debug)
+		ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max);
+}
+
+static int make_trunk(unsigned short callno, int locked)
+{
+	int x;
+	int res= 0;
+	struct timeval now;
+	if (iaxs[callno]->oseqno) {
+		ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n");
+		return -1;
+	}
+	if (callno & TRUNK_CALL_START) {
+		ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno);
+		return -1;
+	}
+	gettimeofday(&now, NULL);
+	for (x=TRUNK_CALL_START;x<AST_IAX2_MAX_CALLS - 1; x++) {
+		ast_pthread_mutex_lock(&iaxsl[x]);
+		if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
+			iaxs[x] = iaxs[callno];
+			iaxs[x]->callno = x;
+			iaxs[callno] = NULL;
+			/* Update the two timers that should have been started */
+			if (iaxs[x]->pingid > -1)
+				ast_sched_del(sched, iaxs[x]->pingid);
+			if (iaxs[x]->lagid > -1)
+				ast_sched_del(sched, iaxs[x]->lagid);
+			iaxs[x]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, (void *)x);
+			iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)x);
+			if (locked)
+				ast_pthread_mutex_unlock(&iaxsl[callno]);
+			res = x;
+			if (!locked)
+				ast_pthread_mutex_unlock(&iaxsl[x]);
+			break;
+		}
+		ast_pthread_mutex_unlock(&iaxsl[x]);
+	}
+	if (x >= AST_IAX2_MAX_CALLS - 1) {
+		ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
+		return -1;
+	}
+	ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x);
+	/* We move this call from a non-trunked to a trunked call */
+	update_max_trunk();
+	update_max_nontrunk();
+	return res;
+}
+
 static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new)
 {
 	int res = 0;
 	int x;
-	int start;
+	struct timeval now;
 	if (new <= NEW_ALLOW) {
 		/* Look for an existing connection first */
-		for (x=0;(res < 1) && (x<AST_IAX2_MAX_CALLS);x++) {
+		for (x=1;(res < 1) && (x<maxnontrunkcall);x++) {
+			ast_pthread_mutex_lock(&iaxsl[x]);
+			if (iaxs[x]) {
+				/* Look for an exact match */
+				if (match(sin, callno, dcallno, iaxs[x])) {
+					res = x;
+				}
+			}
+			ast_pthread_mutex_unlock(&iaxsl[x]);
+		}
+		for (x=TRUNK_CALL_START;(res < 1) && (x<maxtrunkcall);x++) {
 			ast_pthread_mutex_lock(&iaxsl[x]);
 			if (iaxs[x]) {
 				/* Look for an exact match */
@@ -951,16 +1056,21 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
 		}
 	}
 	if ((res < 1) && (new >= NEW_ALLOW)) {
-		/* Create a new one */
-		start = nextcallno;
-		for (x = ((nextcallno + 1) % (AST_IAX2_MAX_CALLS - 1)) + 1; iaxs[x] && (x != start); x = (x + 1) % AST_IAX2_MAX_CALLS)
-		if (x == start) {
-			ast_log(LOG_WARNING, "Unable to accept more calls\n");
-			return 0;
+		gettimeofday(&now, NULL);
+		for (x=1;x<TRUNK_CALL_START;x++) {
+			/* Find first unused call number that hasn't been used in a while */
+			ast_pthread_mutex_lock(&iaxsl[x]);
+			if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) break;
+			ast_pthread_mutex_unlock(&iaxsl[x]);
+		}
+		/* We've still got lock held if we found a spot */
+		if (x >= TRUNK_CALL_START) {
+			ast_log(LOG_WARNING, "No more space\n");
+			return -1;
 		}
-		ast_pthread_mutex_lock(&iaxsl[x]);
 		iaxs[x] = new_iax();
 		ast_pthread_mutex_unlock(&iaxsl[x]);
+		update_max_nontrunk();
 		if (iaxs[x]) {
 			if (option_debug)
 				ast_log(LOG_DEBUG, "Creating new call structure %d\n", x);
@@ -980,7 +1090,6 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
 			return 0;
 		}
 		res = x;
-		nextcallno = x;
 	}
 	return res;
 }
@@ -1192,6 +1301,7 @@ retry:
 	ast_pthread_mutex_lock(&iaxsl[callno]);
 	pvt = iaxs[callno];
 	iaxs[callno] = NULL;
+	gettimeofday(&lastused[callno], NULL);
 
 	if (pvt)
 		owner = pvt->owner;
@@ -1245,6 +1355,8 @@ retry:
 		ast_pthread_mutex_unlock(&owner->lock);
 	}
 	ast_pthread_mutex_unlock(&iaxsl[callno]);
+	if (callno & 0x4000)
+		update_max_trunk();
 }
 static void iax2_destroy_nolock(int callno)
 {	
@@ -1685,7 +1797,7 @@ static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newcha
 	return 0;
 }
 
-static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, int *maxtime, char *peer, char *context)
+static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, int *maxtime, char *peer, char *context, int *trunk)
 {
 	struct hostent *hp;
 	struct iax2_peer *p;
@@ -1694,14 +1806,14 @@ static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, i
 		*sendani = 0;
 	if (maxtime)
 		*maxtime = 0;
+	if (trunk)
+		*trunk = 0;
 	sin->sin_family = AF_INET;
 	ast_pthread_mutex_lock(&peerl.lock);
 	p = peerl.peers;
 	while(p) {
 		if (!strcasecmp(p->name, peer)) {
 			found++;
-			if (capability)
-				*capability = p->capability;
 			if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
 				(!p->maxms || ((p->lastms > 0)  && (p->lastms <= p->maxms)))) {
 				if (sendani)
@@ -1710,6 +1822,10 @@ static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, i
 					*maxtime = p->maxms;		/* Max time they should take */
 				if (context)
 					strncpy(context, p->context, AST_MAX_EXTENSION - 1);
+				if (trunk)
+					*trunk = p->trunk;
+				if (capability)
+					*capability = p->capability;
 				if (p->addr.sin_addr.s_addr) {
 					sin->sin_addr = p->addr.sin_addr;
 					sin->sin_port = p->addr.sin_port;
@@ -1847,7 +1963,7 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
 		strsep(&stringp, ":");
 		portno = strsep(&stringp, ":");
 	}
-	if (create_addr(&sin, NULL, NULL, NULL, hname, context)) {
+	if (create_addr(&sin, NULL, NULL, NULL, hname, context, NULL)) {
 		ast_log(LOG_WARNING, "No address associated with '%s'\n", hname);
 		return -1;
 	}
@@ -2213,6 +2329,46 @@ static struct ast_channel *ast_iax2_new(struct chan_iax2_pvt *i, int state, int
 	return tmp;
 }
 
+static unsigned int calc_txpeerstamp(struct iax2_peer *peer)
+{
+	struct timeval tv;
+	unsigned int mssincetx;
+	unsigned int ms;
+	gettimeofday(&tv, NULL);
+	mssincetx = (tv.tv_sec - peer->lasttxtime.tv_sec) * 1000 + (tv.tv_usec - peer->lasttxtime.tv_usec) / 1000;
+	if (mssincetx > 5000) {
+		/* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
+		peer->txtrunktime.tv_sec = tv.tv_sec;
+		peer->txtrunktime.tv_usec = tv.tv_usec;
+	}
+	/* Update last transmit time now */
+	peer->lasttxtime.tv_sec = tv.tv_sec;
+	peer->lasttxtime.tv_usec = tv.tv_usec;
+	
+	/* Calculate ms offset */
+	ms = (tv.tv_sec - peer->txtrunktime.tv_sec) * 1000 + (tv.tv_usec - peer->txtrunktime.tv_usec) / 1000;
+	
+	/* We never send the same timestamp twice, so fudge a little if we must */
+	if (ms == peer->lastsent)
+		ms = peer->lastsent + 1;
+	peer->lastsent = ms;
+	return ms;
+}
+
+static unsigned int fix_peerts(struct iax2_peer *peer, int callno, unsigned int ts)
+{
+	long ms;	/* NOT unsigned */
+	if (!iaxs[callno]->rxcore.tv_sec && !iaxs[callno]->rxcore.tv_usec) {
+		/* Initialize rxcore time if appropriate */
+		gettimeofday(&iaxs[callno]->rxcore, NULL);
+	}
+	/* Calculate difference between trunk and channel */
+	ms = (peer->rxtrunktime.tv_sec - iaxs[callno]->rxcore.tv_sec) * 1000 + 
+		(peer->rxtrunktime.tv_usec - iaxs[callno]->rxcore.tv_usec) / 1000;
+	/* Return as the sum of trunk time and the difference between trunk and real time */
+	return ms + ts;
+}
+
 static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts)
 {
 	struct timeval tv;
@@ -2249,7 +2405,7 @@ static unsigned int calc_fakestamp(struct chan_iax2_pvt *p1, struct chan_iax2_pv
 	   Adding rxcore to it gives us when we would want the packet to be delivered normally.
 	   Subtracting txcore of the outgoing channel gives us what we'd expect */
 	
-	ms = (p1->rxcore.tv_sec - p2->offset.tv_sec) * 1000 + (p1->rxcore.tv_usec - p1->offset.tv_usec) / 1000;
+	ms = (p1->rxcore.tv_sec - p2->offset.tv_sec) * 1000 + (p1->rxcore.tv_usec - p2->offset.tv_usec) / 1000;
 	fakets += ms;
 	if (fakets <= p2->lastsent)
 		fakets = p2->lastsent + 1;
@@ -2357,20 +2513,34 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
 		} else
 			res = iax2_transmit(fr);
 	} else {
-		/* Mini-frames have no sequence number */
-		fr->oseqno = -1;
-		fr->iseqno = -1;
-		/* Mini frame will do */
-		mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
-		mh->callno = htons(fr->callno);
-		mh->ts = htons(fr->ts & 0xFFFF);
-		fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
-		fr->data = mh;
-		fr->retries = -1;
-		if (now) {
-			res = send_packet(fr);
-		} else
-			res = iax2_transmit(fr);
+		if (pvt->trunk) {
+			/* Queue for transmission in a meta frame */
+			if ((sizeof(pvt->trunkdata) - pvt->trunkdatalen) >= fr->af.datalen) {
+				memcpy(pvt->trunkdata + pvt->trunkdatalen, fr->af.data, fr->af.datalen);
+				pvt->trunkdatalen += fr->af.datalen;
+				res = 0;
+				pvt->trunkerror = 0;
+			} else {
+				if (!pvt->trunkerror)
+					ast_log(LOG_WARNING, "Out of trunk data space on call number %d, dropping\n", pvt->callno);
+				pvt->trunkerror = 1;
+			}
+		} else {
+			/* Mini-frames have no sequence number */
+			fr->oseqno = -1;
+			fr->iseqno = -1;
+			/* Mini frame will do */
+			mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
+			mh->callno = htons(fr->callno);
+			mh->ts = htons(fr->ts & 0xFFFF);
+			fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
+			fr->data = mh;
+			fr->retries = -1;
+			if (now) {
+				res = send_packet(fr);
+			} else
+				res = iax2_transmit(fr);
+		}
 	}
 	return res;
 }
@@ -2400,7 +2570,7 @@ static int iax2_show_users(int fd, int argc, char *argv[])
 static int iax2_show_peers(int fd, int argc, char *argv[])
 {
 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %-10s\n"
-#define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-8d  %-10s\n"
+#define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %-10s\n"
 	struct iax2_peer *peer;
 	char name[256] = "";
 	if (argc != 3)
@@ -2430,7 +2600,7 @@ static int iax2_show_peers(int fd, int argc, char *argv[])
 					peer->addr.sin_addr.s_addr ? inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
 					peer->dynamic ? "(D)" : "(S)",
 					nm,
-					ntohs(peer->addr.sin_port), status);
+					ntohs(peer->addr.sin_port), peer->trunk ? "(T)" : "   ", status);
 	}
 	ast_pthread_mutex_unlock(&peerl.lock);
 	return RESULT_SUCCESS;
@@ -2723,6 +2893,8 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies
 			/* Store the requested username if not specified */
 			if (!strlen(iaxs[callno]->username))
 				strncpy(iaxs[callno]->username, user->name, sizeof(iaxs[callno]->username)-1);
+			/* Store whether this is a trunked call, too, of course, and move if appropriate */
+			iaxs[callno]->trunk = user->trunk;
 			/* And use the default context */
 			if (!strlen(iaxs[callno]->context)) {
 				if (user->contexts)
@@ -3627,19 +3799,115 @@ static int parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
 	return 0;
 }
 
+static int send_trunk(struct iax2_peer *peer)
+{
+	int x;
+	int calls = 0;
+	int res = 0;
+	int firstcall = 0;
+	unsigned char buf[65536 + sizeof(struct ast_iax2_frame)], *ptr;
+	int len = 65536;
+	struct ast_iax2_frame *fr;
+	struct ast_iax2_meta_hdr *meta;
+	struct ast_iax2_meta_trunk_hdr *mth;
+	struct ast_iax2_meta_trunk_entry *met;
+	
+	/* Point to frame */
+	fr = (struct ast_iax2_frame *)buf;
+	/* Point to meta data */
+	meta = (struct ast_iax2_meta_hdr *)fr->afdata;
+	mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
+	/* Point past meta data for first meta trunk entry */
+	ptr = fr->afdata + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
+	len -= sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
+	
+	/* Search through trunked calls for a match with this peer */
+	for (x=TRUNK_CALL_START;x<maxtrunkcall; x++) {
+		ast_pthread_mutex_lock(&iaxsl[x]);
+		if (iaxs[x] && iaxs[x]->trunk && iaxs[x]->trunkdatalen && !memcmp(&iaxs[x]->addr, &peer->addr, sizeof(iaxs[x]->addr))) {
+			if (len >= iaxs[x]->trunkdatalen + sizeof(struct ast_iax2_meta_trunk_entry)) {
+				met = (struct ast_iax2_meta_trunk_entry *)ptr;
+				/* Store call number and length in meta header */
+				met->callno = htons(x);
+				met->len = htons(iaxs[x]->trunkdatalen);
+				/* Advance pointers/decrease length past trunk entry header */
+				ptr += sizeof(struct ast_iax2_meta_trunk_entry);
+				len -= sizeof(struct ast_iax2_meta_trunk_entry);
+				/* Copy actual trunk data */
+				memcpy(ptr, iaxs[x]->trunkdata, iaxs[x]->trunkdatalen);
+				/* Advance pointeres/decrease length for actual data */
+				ptr += iaxs[x]->trunkdatalen;
+				len -= iaxs[x]->trunkdatalen;
+			} else 
+				ast_log(LOG_WARNING, "Out of space in frame for trunking call %d\n", x);
+			iaxs[x]->trunkdatalen = 0;
+			calls++;
+			if (!firstcall)
+				firstcall = x;
+		}
+		ast_pthread_mutex_unlock(&iaxsl[x]);
+	}
+	if (calls) {
+		/* We're actually sending a frame, so fill the meta trunk header and meta header */
+		meta->zeros = 0;
+		meta->metacmd = IAX_META_TRUNK;
+		meta->cmddata = 0;
+		mth->ts = htonl(calc_txpeerstamp(peer));
+		/* And the rest of the ast_iax2 header */
+		fr->direction = DIRECTION_OUTGRESS;
+		fr->retrans = -1;
+		fr->transfer = 0;
+		/* Any appropriate call will do */
+		fr->callno = firstcall;
+		fr->data = fr->afdata;
+		fr->datalen = 65536 - len;
+#if 0
+		ast_log(LOG_DEBUG, "Trunking %d calls in %d bytes, ts=%d\n", calls, fr->datalen, ntohl(mth->ts));
+#endif		
+		res = send_packet(fr);
+	}
+	return res;
+}
+
+static int timing_read(int *id, int fd, short events, void *cbdata)
+{
+	char buf[1024];
+	int res;
+	struct iax2_peer *peer;
+	/* Read and ignore from the pseudo channel for timing */
+	res = read(fd, buf, sizeof(buf));
+	if (res > 0) {
+		/* For each peer that supports trunking... */
+		ast_pthread_mutex_lock(&peerl.lock);
+		peer = peerl.peers;
+		while(peer) {
+			if (peer->trunk) {
+				send_trunk(peer);
+			}
+			peer = peer->next;
+		}
+		ast_pthread_mutex_unlock(&peerl.lock);
+	}
+	return 1;
+}
+
 static int socket_read(int *id, int fd, short events, void *cbdata)
 {
 	struct sockaddr_in sin;
 	int res;
 	int updatehistory=1;
 	int new = NEW_PREVENT;
-	char buf[4096];
+	char buf[4096], *ptr;
 	int len = sizeof(sin);
 	int dcallno = 0;
 	struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)buf;
 	struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)buf;
 	struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)buf;
-	struct ast_iax2_frame fr, *cur;
+	struct ast_iax2_meta_trunk_hdr *mth;
+	struct ast_iax2_meta_trunk_entry *mte;
+	char dblbuf[4096];	/* Declaration of dblbuf must immediately *preceed* fr  on the stack */
+	struct ast_iax2_frame fr;
+	struct ast_iax2_frame *cur;
 	struct ast_frame f;
 	struct ast_channel *c;
 	struct iax2_dpcache *dp;
@@ -3649,7 +3917,9 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
 	int format;
 	int exists;
 	int mm;
+	unsigned int ts;
 	char empty[32]="";		/* Safety measure */
+	dblbuf[0] = 0;	/* Keep GCC from whining */
 	res = recvfrom(netsocket, buf, sizeof(buf), 0,(struct sockaddr *) &sin, &len);
 	if (res < 0) {
 		if (errno != ECONNREFUSED)
@@ -3663,7 +3933,92 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
 	}
 	if (meta->zeros == 0) {
 		/* This is a a meta header */
-		ast_log(LOG_DEBUG, "Meta header  Command = %d!\n", meta->metacmd);
+		switch(meta->metacmd) {
+		case IAX_META_TRUNK:
+			if (res < sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) {
+				ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %d min)\n", res, sizeof(struct ast_iax2_mini_hdr));
+				return 1;
+			}
+			mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data);
+			ts = ntohl(mth->ts);
+			res -= (sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr));
+			ptr = mth->data;
+			ast_pthread_mutex_lock(&peerl.lock);
+			peer = peerl.peers;
+			while(peer) {
+				if (!memcmp(&peer->addr, &sin, sizeof(peer->addr)))
+					break;
+				peer = peer->next;
+			}
+			ast_pthread_mutex_unlock(&peerl.lock);
+			if (!peer) {
+				ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+				return 1;
+			}
+			if (!ts || (!peer->rxtrunktime.tv_sec && !peer->rxtrunktime.tv_usec)) {
+				gettimeofday(&peer->rxtrunktime, NULL);
+			}
+			while(res >= sizeof(struct ast_iax2_meta_trunk_entry)) {
+				/* Process channels */
+				mte = (struct ast_iax2_meta_trunk_entry *)ptr;
+				ptr += sizeof(struct ast_iax2_meta_trunk_entry);
+				res -= sizeof(struct ast_iax2_meta_trunk_entry);
+				len = ntohs(mte->len);
+				/* Stop if we don't have enough data */
+				if (len > res)
+					break;
+				fr.callno = find_callno(ntohs(mte->callno) & ~AST_FLAG_FULL, 0, &sin, NEW_PREVENT);
+				if (fr.callno) {
+					ast_pthread_mutex_lock(&iaxsl[fr.callno]);
+					/* If it's a valid call, deliver the contents.  If not, we
+					   drop it, since we don't have a scallno to use for an INVAL */
+					/* Process as a mini frame */
+					f.frametype = AST_FRAME_VOICE;
+					if (iaxs[fr.callno]->voiceformat > 0) {
+						f.subclass = iaxs[fr.callno]->voiceformat;
+						f.datalen = len;
+						if (f.datalen >= 0) {
+							if (f.datalen)
+								f.data = ptr;
+							else
+								f.data = NULL;
+							fr.ts = fix_peerts(peer, fr.callno, ts);
+							/* Don't pass any packets until we're started */
+							if ((iaxs[fr.callno]->state & IAX_STATE_STARTED)) {
+								/* Common things */
+								f.src = "IAX2";
+								f.mallocd = 0;
+								f.offset = 0;
+								if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 
+									f.samples = get_samples(&f);
+								else
+									f.samples = 0;
+								fr.outoforder = 0;
+								ast_iax2_frame_wrap(&fr, &f);
+#ifdef BRIDGE_OPTIMIZATION
+								if (iaxs[fr.callno]->bridgecallno) {
+									forward_delivery(&fr);
+								} else {
+									schedule_delivery(iaxfrdup2(&fr), 1, updatehistory);
+								}
+#else
+								schedule_delivery(iaxfrdup2(&fr), 1, updatehistory);
+#endif
+							}
+						} else {
+							ast_log(LOG_WARNING, "Datalen < 0?\n");
+						}
+					} else {
+						ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n ");
+						iax2_vnak(fr.callno);
+					}
+					ast_pthread_mutex_unlock(&iaxsl[fr.callno]);
+				}
+				ptr += len;
+				res -= len;
+			}
+			
+		}
 		return 1;
 	}
 #ifdef DEBUG_SUPPORT
@@ -3776,7 +4131,7 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
 		/* Handle implicit ACKing unless this is an INVAL */
 		if (((f.subclass != AST_IAX2_COMMAND_INVAL)) ||
 			(f.frametype != AST_FRAME_IAX)) {
-			int x;
+			unsigned char x;
 			/* XXX This code is not very efficient.  Surely there is a better way which still
 			       properly handles boundary conditions? XXX */
 			/* First we have to qualify that the ACKed value is within our window */
@@ -3903,6 +4258,10 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
 					ast_log(LOG_NOTICE, "Rejected connect attempt from %s\n", inet_ntoa(sin.sin_addr));
 					break;
 				}
+				/* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */
+				if (iaxs[fr.callno]->trunk) {
+					fr.callno = make_trunk(fr.callno, 1);
+				}
 				/* This might re-enter the IAX code and need the lock */
 				exists = ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->callerid);
 				if (!strlen(iaxs[fr.callno]->secret) && !strlen(iaxs[fr.callno]->inkeys)) {
@@ -4502,6 +4861,7 @@ static struct ast_channel *iax2_request(char *type, int format, void *data)
 	struct ast_channel *c;
 	char *stringp=NULL;
 	int capability = iax2_capability;
+	int trunk;
 	strncpy(s, (char *)data, sizeof(s)-1);
 	/* FIXME The next two lines seem useless */
 	stringp=s;
@@ -4513,7 +4873,7 @@ static struct ast_channel *iax2_request(char *type, int format, void *data)
 	if (!st)
 		st = s;
 	/* Populate our address from the given */
-	if (create_addr(&sin, &capability, &sendani, &maxtime, st, NULL)) {
+	if (create_addr(&sin, &capability, &sendani, &maxtime, st, NULL, &trunk)) {
 		return NULL;
 	}
 	callno = find_callno(0, 0, &sin, NEW_FORCE);
@@ -4522,6 +4882,10 @@ static struct ast_channel *iax2_request(char *type, int format, void *data)
 		return NULL;
 	}
 	ast_pthread_mutex_lock(&iaxsl[callno]);
+	/* If this is a trunk, update it now */
+	iaxs[callno]->trunk = trunk;
+	if (trunk) 
+		callno = make_trunk(callno, 1);
 	/* Keep track of sendani flag */
 	iaxs[callno]->sendani = sendani;
 	iaxs[callno]->maxtime = maxtime;
@@ -4554,6 +4918,8 @@ static void *network_thread(void *ignore)
 	struct ast_iax2_frame *f, *freeme;
 	/* Establish I/O callback for socket read */
 	ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL);
+	if (timingfd > -1)
+		ast_io_add(io, timingfd, timing_read, AST_IO_IN, NULL);
 	for(;;) {
 		/* Go through the queue, sending messages which have not yet been
 		   sent, and scheduling retransmissions if appropriate */
@@ -4674,9 +5040,13 @@ static struct iax2_peer *build_peer(char *name, struct ast_variable *v)
 				strncpy(peer->secret, v->value, sizeof(peer->secret)-1);
 			else if (!strcasecmp(v->name, "mailbox"))
 				strncpy(peer->mailbox, v->value, sizeof(peer->mailbox) - 1);
-			else if (!strcasecmp(v->name, "trunk"))
-				peer->trunk = 1;
-			else if (!strcasecmp(v->name, "auth")) {
+			else if (!strcasecmp(v->name, "trunk")) {
+				peer->trunk = ast_true(v->value);
+				if (peer->trunk && (timingfd < 0)) {
+					ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name);
+					peer->trunk = 0;
+				}
+			} else if (!strcasecmp(v->name, "auth")) {
 				peer->authmethods = get_auth_methods(v->value);
 			} else if (!strcasecmp(v->name, "host")) {
 				if (!strcasecmp(v->value, "dynamic")) {
@@ -4789,12 +5159,16 @@ static struct iax2_user *build_user(char *name, struct ast_variable *v)
 			} else if (!strcasecmp(v->name, "permit") ||
 					   !strcasecmp(v->name, "deny")) {
 				user->ha = ast_append_ha(v->name, v->value, user->ha);
+			} else if (!strcasecmp(v->name, "trunk")) {
+				user->trunk = ast_true(v->value);
+				if (user->trunk && (timingfd < 0)) {
+					ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name);
+					user->trunk = 0;
+				}
 			} else if (!strcasecmp(v->name, "auth")) {
 				user->authmethods = get_auth_methods(v->value);
 			} else if (!strcasecmp(v->name, "secret")) {
 				strncpy(user->secret, v->value, sizeof(user->secret)-1);
-			} else if (!strcasecmp(v->name, "trunk")) {
-				user->trunk = 1;
 			} else if (!strcasecmp(v->name, "callerid")) {
 				strncpy(user->callerid, v->value, sizeof(user->callerid)-1);
 				user->hascallerid=1;
@@ -4814,7 +5188,7 @@ static struct iax2_user *build_user(char *name, struct ast_variable *v)
 			v = v->next;
 		}
 	}
-	if (user->authmethods) {
+	if (!user->authmethods) {
 		if (strlen(user->secret)) {
 			user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
 			if (strlen(user->inkeys))
@@ -4898,6 +5272,17 @@ void prune_peers(void){
 	ast_pthread_mutex_unlock(&peerl.lock);
 }
 
+static void set_timing(void)
+{
+#ifdef IAX_TRUNKING
+	int bs = trunkfreq * 8;
+	if (timingfd > -1) {
+		if (ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
+			ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
+	}
+#endif
+}
+
 
 static int set_config(char *config_file, struct sockaddr_in* sin){
 	struct ast_config *cfg;
@@ -4946,7 +5331,11 @@ static int set_config(char *config_file, struct sockaddr_in* sin){
 			inet_aton(v->value, &sin->sin_addr);
 		else if (!strcasecmp(v->name, "jitterbuffer"))
 			use_jitterbuffer = ast_true(v->value);
-		else if (!strcasecmp(v->name, "bandwidth")) {
+		else if (!strcasecmp(v->name, "trunkfreq")) {
+			trunkfreq = atoi(v->value);
+			if (trunkfreq < 10)
+				trunkfreq = 10;
+		} else if (!strcasecmp(v->name, "bandwidth")) {
 			if (!strcasecmp(v->value, "low")) {
 				capability = IAX_CAPABILITY_LOWBANDWIDTH;
 			} else if (!strcasecmp(v->value, "medium")) {
@@ -5029,6 +5418,7 @@ static int set_config(char *config_file, struct sockaddr_in* sin){
 		cat = ast_category_browse(cfg, cat);
 	}
 	ast_destroy(cfg);
+	set_timing();
 	return capability;
 }
 
@@ -5102,7 +5492,7 @@ static int cache_get_callno(char *data)
 		host = st;
 	}
 	/* Populate our address from the given */
-	if (create_addr(&sin, NULL, NULL, NULL, host, NULL)) {
+	if (create_addr(&sin, NULL, NULL, NULL, host, NULL, NULL)) {
 		return -1;
 	}
 	ast_log(LOG_DEBUG, "host: %s, user: %s, password: %s, context: %s\n", host, username, password, context);
@@ -5419,6 +5809,12 @@ int load_module(void)
 	sin.sin_port = ntohs(AST_DEFAULT_IAX_PORTNO);
 	sin.sin_addr.s_addr = INADDR_ANY;
 
+#ifdef IAX_TRUNKING
+	timingfd = open("/dev/zap/pseudo", O_RDWR);
+	if (timingfd < 0) 
+		ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
+#endif		
+
 	for (x=0;x<AST_IAX2_MAX_CALLS;x++)
 		ast_pthread_mutex_init(&iaxsl[x]);
 	
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 385c483892ecb1e510e7cb92879937a3fbfed067..a13f37158232ce926a62af3547ef7fa96409d3b5 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -307,6 +307,7 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp);
 static int transmit_info_with_digit(struct sip_pvt *p, char digit);
 static int transmit_message_with_text(struct sip_pvt *p, char *text);
 static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req);
+char *getsipuri(char *header);
 
 static int __sip_xmit(struct sip_pvt *p, char *data, int len)
 {
@@ -1653,6 +1654,7 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, stru
 	copy_via_headers(p, resp, req, "Via");
 	copy_header(resp, req, "From");
 	ot = get_header(req, "To");
+	copy_header(resp, req, "Record-Route");
 	if (!strstr(ot, "tag=")) {
 		/* Add the proper tag if we don't have it already.  If they have specified
 		   their tag, use it.  Otherwise, use our own tag */
@@ -1672,20 +1674,28 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, stru
 		/* For registration responses, we also need expirey and
 		   contact info */
 		char tmp[80];
-		char contact2[256] = "", *c, contact[256];
+		char contact[256];
+		char *c;
+		if ((c=getsipuri(ot))) {
+			snprintf(contact, sizeof(contact), "<%s@%s>", c, inet_ntoa(p->ourip));
+			free(c);
+		} else {
+			snprintf(contact, sizeof(contact), "<%s>", inet_ntoa(p->ourip));
+		}
 		snprintf(tmp, sizeof(tmp), "%d", p->expirey);
-		strncpy(contact2, get_header(req, "Contact"), sizeof(contact2)-1);
-		c = ditch_braces(contact2);
-		snprintf(contact, sizeof(contact), "<%s>", c);
 		add_header(resp, "Expires", tmp);
 		add_header(resp, "Contact", contact);
 	} else {
-		char contact2[256] = "", *c, contact[256];
+		char contact[256];
 		/* XXX This isn't exactly right and it's implemented
 		       very stupidly *sigh* XXX */
-		strncpy(contact2, get_header(req, "To"), sizeof(contact2)-1);
-		c = ditch_braces(contact2);
-		snprintf(contact, sizeof(contact), "<%s>", c);
+		char *c;
+		if ((c=getsipuri(ot))) {
+			snprintf(contact, sizeof(contact), "<%s@%s>", c, inet_ntoa(p->ourip));
+			free(c);
+		} else {
+			snprintf(contact, sizeof(contact), "<%s>", inet_ntoa(p->ourip));
+		}
 		add_header(resp, "Contact", contact);
 	}
 	return 0;
@@ -4543,3 +4553,24 @@ char *description()
 	return desc;
 }
 
+char *getsipuri(char *header)
+{
+	char *c, *d, *retval;
+	int n;
+
+	if (!(c=strstr(header, "sip"))) {
+		return NULL;
+	}
+
+	if (!(d=strchr(c, '@'))) {
+		return NULL;
+	}
+
+	n=d-c;
+
+	retval=(char *)malloc(n+1);
+	strncpy(retval, c, n);
+	*(retval+n)='\0';
+
+	return retval;
+}
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index 91a1ac5336e7bacc2a417c9fcea9564fabb2ec02..c76791f4f524562a209c94a04900549bd8cead40 100755
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -1315,6 +1315,10 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
 		} else {
 			strcpy(p->dop.dialstr, "");
 		}
+		if (!(p->call = pri_new_call(p->pri->pri))) {
+			ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
+			return -1;
+		}
 		if (pri_call(p->pri->pri, p->call, p->digital ? PRI_TRANS_CAP_DIGITAL : PRI_TRANS_CAP_SPEECH, 
 			p->prioffset, p->pri->nodetype == PRI_NETWORK ? 0 : 1, 1, l, p->pri->dialplan - 1, n,
 			l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE,
@@ -4932,13 +4936,6 @@ static struct ast_channel *zt_request(char *type, int format, void *data)
 					p = p->next;
 					continue;
 				}
-#ifdef ZAPATA_PRI
-			if (p->pri) 
-				if (!(p->call = pri_new_call(p->pri->pri))) {
-					ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
-					break;
-				}
-#endif
 			callwait = (p->owner != NULL);
 			if (p->channel == CHAN_PSEUDO) {
 				p = chandup(p);
diff --git a/channels/iax2.h b/channels/iax2.h
index a51e7cdf1a3a663033323266316177311c74b91b..5d911f75079e9ae99dfe62e95906f520a5ce4bc8 100755
--- a/channels/iax2.h
+++ b/channels/iax2.h
@@ -138,11 +138,11 @@ struct ast_iax2_meta_hdr {
 struct ast_iax2_meta_trunk_hdr {
 	unsigned int ts;				/* 32-bit timestamp for all messages */
 	unsigned char data[0];
-};
+} __attribute__ ((__packed__));
 
 struct ast_iax2_meta_trunk_entry {
 	unsigned short callno;			/* Call number */
 	unsigned short len;				/* Length of data for this callno */
-};
+} __attribute__ ((__packed__));
 
 #endif
diff --git a/configs/iax.conf.sample b/configs/iax.conf.sample
index 2b089c982f833d3c7825b605fe0fe242535f0a2a..77bd7870cde80cfc5affe8948e38d805d09dd1ca 100755
--- a/configs/iax.conf.sample
+++ b/configs/iax.conf.sample
@@ -47,6 +47,9 @@ disallow=lpc10			; Icky sound quality...  Mr. Roboto.
 ;maxjitterbuffer=500
 ;maxexccessbuffer=100
 ;
+;trunkfreq=20			; How frequently to send trunk msgs (in ms)
+;
+;
 ; We can register with another IAX server to let him know where we are
 ; in case we have a dynamic IP address for example
 ;
diff --git a/utils/astman.c b/utils/astman.c
index 6fa6b811821e7369102010af4d3e2e0eb314c5ea..2eb35f68e5ba85cfb3a5442ddbec4a5cd3d3e078 100755
--- a/utils/astman.c
+++ b/utils/astman.c
@@ -383,14 +383,14 @@ static int show_doing(char *title, char *tmp)
 	return 0;
 }
 
-static int hide_doing()
+static int hide_doing(void)
 {
 	newtPopWindow();
 	newtFormDestroy(showform);
 	return 0;
 }
 
-static void try_status()
+static void try_status(void)
 {
 	struct message *m;
 	manager_action("Status", "");