Index: channels/chan_iax2.c
===================================================================
--- channels/chan_iax2.c	(revision 128742)
+++ channels/chan_iax2.c	(revision 128799)
@@ -204,6 +204,23 @@
 #define DEFAULT_FREQ_OK		60 * 1000	/* How often to check for the host to be up */
 #define DEFAULT_FREQ_NOTOK	10 * 1000	/* How often to check, if the host is down... */
 
+/* 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))
+
+#define IAX_DEBUGDIGEST(msg, key) do { \
+		int idx; \
+		char digest[33] = ""; \
+		\
+		if (!iaxdebug) \
+			break; \
+		\
+		for (idx = 0; idx < 16; idx++) \
+			sprintf(digest + (idx << 1), "%2.2x", (unsigned char) key[idx]); \
+		\
+		ast_log(LOG_NOTICE, msg " IAX_COMMAND_RTKEY to rotate key to '%s'\n", digest); \
+	} while(0)
+
 static	struct io_context *io;
 static	struct sched_context *sched;
 
@@ -588,6 +605,9 @@
 	ast_aes_encrypt_key ecx;
 	/*! Decryption AES-128 Key */
 	ast_aes_decrypt_key dcx;
+	/*! scheduler id associated with iax_key_rotate 
+	 * for encrypted calls*/
+	int keyrotateid;
 	/*! 32 bytes of semi-random data */
 	unsigned char semirand[32];
 	/*! Associated registry */
@@ -1391,6 +1411,7 @@
 	AST_SCHED_DEL(sched, pvt->authid);
 	AST_SCHED_DEL(sched, pvt->initid);
 	AST_SCHED_DEL(sched, pvt->jbid);
+	AST_SCHED_DEL(sched, pvt->keyrotateid);
 }
 
 static void iax2_frame_free(struct iax_frame *fr)
@@ -1459,6 +1480,7 @@
 	tmp->autoid = -1;
 	tmp->authid = -1;
 	tmp->initid = -1;
+	tmp->keyrotateid = -1;
 
 	ast_string_field_set(tmp,exten, "s");
 	ast_string_field_set(tmp,host, host);
@@ -3766,12 +3788,54 @@
 	return &ast_null_frame;
 }
 
+static int iax2_key_rotate(const void *vpvt) {
+	int res = 0;
+	struct chan_iax2_pvt *pvt = (void *) vpvt;
+	struct MD5Context md5;
+	char key[17] = "";
+	struct iax_ie_data ied;
+	
+	memset(&ied, '\0', sizeof(ied));
+
+	ast_mutex_lock(&iaxsl[pvt->callno]);
+
+	pvt->keyrotateid = 
+		ast_sched_add(sched, 120000 + (ast_random() % 180001), iax2_key_rotate, vpvt);
+
+
+	snprintf(key, sizeof(key), "%lX", ast_random());
+
+	MD5Init(&md5);
+	MD5Update(&md5, (unsigned char *) key, strlen(key));
+	MD5Final((unsigned char *) key, &md5);
+
+	IAX_DEBUGDIGEST("Sending", key);
+
+	iax_ie_append_raw(&ied, IAX_IE_CHALLENGE, key, 16);
+
+	res = send_command(pvt, AST_FRAME_IAX, IAX_COMMAND_RTKEY, 0, ied.buf, ied.pos, -1);
+
+	ast_aes_encrypt_key((unsigned char *) key, &pvt->ecx);
+
+	ast_mutex_unlock(&iaxsl[pvt->callno]);
+
+	return res;
+}
+
 static int iax2_start_transfer(unsigned short callno0, unsigned short callno1, int mediaonly)
 {
 	int res;
 	struct iax_ie_data ied0;
 	struct iax_ie_data ied1;
 	unsigned int transferid = (unsigned int)ast_random();
+
+	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);
+		return 0;
+	}
+
 	memset(&ied0, 0, sizeof(ied0));
 	iaxs[callno0]->transferid = transferid;
 	iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
@@ -4676,8 +4740,18 @@
 	 * (the endpoint should detect the lost packet itself).  But, we want to do this here, so that we
 	 * increment the "predicted timestamps" for voice, if we're predicting */
 	if(f->frametype == AST_FRAME_VOICE && f->datalen == 0)
-	    return 0;
+		return 0;
+#if 0
+	ast_log(LOG_NOTICE, 
+		"f->frametype %c= AST_FRAME_VOICE, %sencrypted, %srotation scheduled...\n",
+		*("=!" + (f->frametype == AST_FRAME_VOICE)),
+		IAX_CALLENCRYPTED(pvt) ? "" : "not ",
+		pvt->keyrotateid != -1 ? "" : "no "
+	);
+#endif
 
+	if (f->frametype == AST_FRAME_VOICE && IAX_CALLENCRYPTED(pvt) && pvt->keyrotateid == -1)
+		iax2_key_rotate(pvt);
 
 	if ((ast_test_flag(pvt, IAX_TRUNK) || 
 			(((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
@@ -7824,7 +7898,7 @@
 		if (!iaxs[fr->callno]) {
 			/* drop it */
 		} else if (iaxs[fr->callno]->voiceformat == 0) {
-			ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n ");
+			ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n");
 			iax2_vnak(fr->callno);
 		} else {
 			f.subclass = iaxs[fr->callno]->voiceformat;
@@ -9397,7 +9471,20 @@
 					iaxs[fr->callno]->transferring = TRANSFER_NONE;
 					iaxs[fr->callno]->mediareleased = 1;
 				}
-				break;	
+				break;
+			case IAX_COMMAND_RTKEY:
+				if (!IAX_CALLENCRYPTED(iaxs[fr->callno])) {
+					ast_log(LOG_WARNING, 
+						"we've been told to rotate our encryption key, "
+						"but this isn't an encrypted call. bad things will happen.\n"
+					);
+					break;
+				}
+
+				IAX_DEBUGDIGEST("Receiving", ies.challenge);
+
+				ast_aes_decrypt_key((unsigned char *) ies.challenge, &iaxs[fr->callno]->dcx);
+				break;
 			case IAX_COMMAND_DPREP:
 				complete_dpreply(iaxs[fr->callno], &ies);
 				break;
@@ -9449,7 +9536,7 @@
 		if (iaxs[fr->callno]->videoformat > 0) 
 			f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0);
 		else {
-			ast_log(LOG_WARNING, "Received mini frame before first full video frame\n ");
+			ast_log(LOG_WARNING, "Received mini frame before first full video frame\n");
 			iax2_vnak(fr->callno);
 			ast_mutex_unlock(&iaxsl[fr->callno]);
 			return 1;
Index: channels/iax2.h
===================================================================
--- channels/iax2.h	(revision 128742)
+++ channels/iax2.h	(revision 128799)
@@ -109,6 +109,8 @@
 	IAX_COMMAND_FWDATA =    37,
 	/*! Transfer media only */
 	IAX_COMMAND_TXMEDIA =   38,
+	/*! Command to rotate key */
+	IAX_COMMAND_RTKEY = 	39,
 };
 
 /*! By default require re-registration once per minute */
Index: apps/app_voicemail.c
===================================================================
--- apps/app_voicemail.c	(revision 128742)
+++ apps/app_voicemail.c	(revision 128799)
@@ -5918,12 +5918,16 @@
 
 	if (box == OLD_FOLDER) {
 		ast_copy_string(vms->curbox, mbox(NEW_FOLDER), sizeof(vms->curbox));
-		snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", mbox(1));
 	} else {
 		ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
-		snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
 	}
 
+	if (box == NEW_FOLDER) {
+		ast_copy_string(vms->vmbox, "vm-INBOX", sizeof(vms->vmbox));
+	} else {
+		snprintf(vms->vmbox, sizeof(vm->vmbox), "vm-%s", mbox(box));
+	}
+
 	/* Build up server information */
 	ast_build_string(&t, &left, "{%s:%s/imap", imapserver, imapport);
 
