[asterisk-commits] russell: branch russell/dtls r207354 - in /team/russell/dtls: channels/ configs/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Jul 19 21:27:34 CDT 2009


Author: russell
Date: Sun Jul 19 21:27:32 2009
New Revision: 207354

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=207354
Log:
Add what I have so far for DTLS in chan_iax2.  Untested.

Modified:
    team/russell/dtls/channels/chan_iax2.c
    team/russell/dtls/configs/iax.conf.sample

Modified: team/russell/dtls/channels/chan_iax2.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/dtls/channels/chan_iax2.c?view=diff&rev=207354&r1=207353&r2=207354
==============================================================================
--- team/russell/dtls/channels/chan_iax2.c (original)
+++ team/russell/dtls/channels/chan_iax2.c Sun Jul 19 21:27:32 2009
@@ -28,6 +28,16 @@
  * \ingroup channel_drivers
  * 
  * \todo Implement musicclass settings for IAX2 devices
+ */
+
+/*!
+ * \page IAX2DTLStodo IAX2 DTLS To-Do
+ *
+ * \section dtlstodo To-Do
+ *  - allow turning off non-dtls support
+ *  - allow multiple DTLS sockets
+ *  - fix reload of DTLS settings
+ *  - Ensure received packets came in on the right connection
  */
 
 /*** MODULEINFO
@@ -89,6 +99,7 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/timing.h"
 #include "asterisk/taskprocessor.h"
+#include "asterisk/dtls.h"
 
 #include "iax2.h"
 #include "iax2-parser.h"
@@ -305,6 +316,11 @@
 static struct ast_netsock_list *outsock;		/*!< used if sourceaddress specified and bindaddr == INADDR_ANY */
 static int defaultsockfd = -1;
 
+static struct {
+	struct ast_dtls_config *config;
+	struct ast_dtls_handler *handler;
+} dtls_data;
+
 static int (*iax2_regfunk)(const char *username, int onoff) = NULL;
 
 /* Ethernet, etc */
@@ -421,6 +437,7 @@
 #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 */
+#define IAX_DTLS                (uint64_t)(1 << 31)   /*!< Use DTLS. */
 
 static int global_rtautoclear = 120;
 
@@ -453,6 +470,22 @@
 	struct ast_ha *ha;
 	struct iax2_context *contexts;
 	struct ast_variable *vars;
+};
+
+enum iax2_socket_type {
+	IAX2_SOCKET_TYPE_NONE,
+	IAX2_SOCKET_TYPE_UDP,
+	IAX2_SOCKET_TYPE_DTLS,
+};
+
+union iax2_socket_data {
+	int sockfd;
+	struct ast_dtls_handler *dtls_handler;
+};
+
+struct iax2_socket {
+	enum iax2_socket_type type;
+	union iax2_socket_data data;
 };
 
 struct iax2_peer {
@@ -480,7 +513,7 @@
 	struct ast_dnsmgr_entry *dnsmgr;		/*!< DNS refresh manager */
 	struct sockaddr_in addr;
 	int formats;
-	int sockfd;					/*!< Socket to use for transmission */
+	struct iax2_socket socket;
 	struct in_addr mask;
 	int adsi;
 	uint64_t flags;
@@ -514,7 +547,7 @@
 
 struct iax2_trunk_peer {
 	ast_mutex_t lock;
-	int sockfd;
+	struct iax2_socket socket;
 	struct sockaddr_in addr;
 	struct timeval txtrunktime;		/*!< Transmit trunktime */
 	struct timeval rxtrunktime;		/*!< Receive trunktime */
@@ -619,7 +652,7 @@
 
 struct chan_iax2_pvt {
 	/*! Socket to send/receive on for this call */
-	int sockfd;
+	struct iax2_socket socket;
 	/*! Last received voice format */
 	int voiceformat;
 	/*! Last received video format */
@@ -909,7 +942,7 @@
 	unsigned char *buf;
 	ssize_t buf_len;
 	size_t buf_size;
-	int iofd;
+	struct iax2_socket socket;
 	time_t checktime;
 	ast_mutex_t lock;
 	ast_cond_t cond;
@@ -1090,7 +1123,8 @@
 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, const char *dest, const char *template, int force);
+static int iax2_provision(struct sockaddr_in *end, struct iax2_socket *socket,
+		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);
@@ -1148,6 +1182,57 @@
 	.func_channel_write = acf_channel_write,
 };
 
+static void iax2_socket_cleanup(struct iax2_socket *socket)
+{
+	switch (socket->type) {
+	case IAX2_SOCKET_TYPE_NONE:
+	case IAX2_SOCKET_TYPE_UDP:
+		break;
+	case IAX2_SOCKET_TYPE_DTLS:
+		if (socket->data.dtls_handler) {
+			socket->data.dtls_handler = ast_dtls_handler_unref(socket->data.dtls_handler);
+		}
+		break;
+	}
+}
+
+static void iax2_socket_copy(struct iax2_socket *dst, struct iax2_socket *src)
+{
+	iax2_socket_cleanup(dst);
+
+	dst->type = src->type;
+
+	switch (src->type) {
+	case IAX2_SOCKET_TYPE_NONE:
+		break;
+	case IAX2_SOCKET_TYPE_UDP:
+		dst->data.sockfd = src->data.sockfd;
+		break;
+	case IAX2_SOCKET_TYPE_DTLS:
+		dst->data.dtls_handler = ast_dtls_handler_ref(src->data.dtls_handler);
+		break;
+	}
+}
+
+static void iax2_socket_set_type(struct iax2_socket *socket,
+		enum iax2_socket_type type, union iax2_socket_data data)
+{
+	iax2_socket_cleanup(socket);
+
+	socket->type = type;
+
+	switch (type) {
+	case IAX2_SOCKET_TYPE_NONE:
+		break;
+	case IAX2_SOCKET_TYPE_UDP:
+		socket->data.sockfd = data.sockfd;
+		break;
+	case IAX2_SOCKET_TYPE_DTLS:
+		socket->data.dtls_handler = ast_dtls_handler_ref(data.dtls_handler);
+		break;
+	}
+}
+
 static void mwi_event_cb(const struct ast_event *event, void *userdata)
 {
 	/* The MWI subscriptions exist just so the core knows we care about those
@@ -1671,6 +1756,8 @@
 		jb_destroy(pvt->jb);
 		ast_string_field_free_memory(pvt);
 	}
+
+	iax2_socket_cleanup(&pvt->socket);
 }
 
 static struct chan_iax2_pvt *new_iax(struct sockaddr_in *sin, const char *host)
@@ -1875,7 +1962,9 @@
 /*
  * \note Calling this function while holding another pvt lock can cause a deadlock.
  */
-static int __find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int return_locked, int check_dcallno)
+static int __find_callno(unsigned short callno, unsigned short dcallno,
+		struct sockaddr_in *sin, int new, struct iax2_socket *socket,
+		int return_locked, int check_dcallno)
 {
 	int res = 0;
 	int x;
@@ -2012,7 +2101,7 @@
 		if (iaxs[x]) {
 			if (iaxdebug)
 				ast_debug(1, "Creating new call structure %d\n", x);
-			iaxs[x]->sockfd = sockfd;
+			iax2_socket_copy(&iaxs[x]->socket, socket);
 			iaxs[x]->addr.sin_port = sin->sin_port;
 			iaxs[x]->addr.sin_family = sin->sin_family;
 			iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr;
@@ -2044,14 +2133,18 @@
 	return res;
 }
 
-static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame) {
-
-	return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame);
-}
-
-static int find_callno_locked(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame) {
-
-	return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame);
+static int find_callno(unsigned short callno, unsigned short dcallno,
+		struct sockaddr_in *sin, int new, struct iax2_socket *socket,
+		int full_frame)
+{
+	return __find_callno(callno, dcallno, sin, new, socket, 0, full_frame);
+}
+
+static int find_callno_locked(unsigned short callno, unsigned short dcallno,
+		struct sockaddr_in *sin, int new, struct iax2_socket *socket,
+		int full_frame)
+{
+	return __find_callno(callno, dcallno, sin, new, socket, 1, full_frame);
 }
 
 /*!
@@ -2452,17 +2545,37 @@
 	return 0;
 }
 
-static int transmit_trunk(struct iax_frame *f, struct sockaddr_in *sin, int sockfd)
-{
-	int res;
-	res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
-					sizeof(*sin));
-	if (res < 0) {
-		ast_debug(1, "Received error: %s\n", strerror(errno));
-		handle_error();
-	} else
-		res = 0;
+static int iax_frame_send(struct iax_frame *f, struct sockaddr_in *sin,
+		struct iax2_socket *socket)
+{
+	int res = -1;
+
+	switch (socket->type) {
+	case IAX2_SOCKET_TYPE_NONE:
+		ast_log(LOG_WARNING, "Can not send frame with no socket!\n");
+		break;
+	case IAX2_SOCKET_TYPE_UDP:
+		res = sendto(socket->data.sockfd, f->data, f->datalen, 0,
+				(struct sockaddr *) sin, sizeof(*sin));
+		if (res < 0) {
+			ast_debug(1, "Received error: %s\n", strerror(errno));
+			handle_error();
+		} else {
+			res = 0;
+		}
+		break;
+	case IAX2_SOCKET_TYPE_DTLS:
+		res = ast_dtls_send(socket->data.dtls_handler, f->data, f->datalen, sin);
+		break;
+	}
+
 	return res;
+}
+
+static int transmit_trunk(struct iax_frame *f, struct sockaddr_in *sin,
+		struct iax2_socket *socket)
+{
+	return iax_frame_send(f, sin, socket);
 }
 
 static int send_packet(struct iax_frame *f)
@@ -2481,11 +2594,11 @@
 	if (f->transfer) {
 		if (iaxdebug)
 			iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
-		res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer, sizeof(iaxs[callno]->transfer));
+		res = iax_frame_send(f, &iaxs[callno]->transfer, &iaxs[callno]->socket);
 	} else {
 		if (iaxdebug)
 			iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
-		res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr, sizeof(iaxs[callno]->addr));
+		res = iax_frame_send(f, &iaxs[callno]->addr, &iaxs[callno]->socket);
 	}
 	if (res < 0) {
 		if (iaxdebug)
@@ -2937,6 +3050,8 @@
 		peer_status(peer, status, sizeof(status));	
 		ast_cli(a->fd, "%s\n",status);
 		ast_cli(a->fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
+		ast_cli(a->fd, "  DTLS         : %s\n",
+				ast_test_flag64(peer, IAX_DTLS) ? "On" : "Off");
 		ast_cli(a->fd, "\n");
 		peer_unref(peer);
 	} else {
@@ -3648,7 +3763,7 @@
 	int maxtime;
 	int encmethods;
 	int found;
-	int sockfd;
+	struct iax2_socket socket;
 	int adsi;
 	char username[80];
 	char secret[80];
@@ -3668,9 +3783,12 @@
 	struct iax2_peer *peer;
 	int res = -1;
 	struct ast_codec_pref ourprefs;
+	union iax2_socket_data socket_data = {
+		.sockfd = defaultsockfd,
+	};
 
 	ast_clear_flag64(cai, IAX_SENDANI | IAX_TRUNK);
-	cai->sockfd = defaultsockfd;
+	iax2_socket_set_type(&cai->socket, IAX2_SOCKET_TYPE_UDP, socket_data);
 	cai->maxtime = 0;
 	sin->sin_family = AF_INET;
 
@@ -3704,7 +3822,7 @@
 	cai->maxtime = peer->maxms;
 	cai->capability = peer->capability;
 	cai->encmethods = peer->encmethods;
-	cai->sockfd = peer->sockfd;
+	iax2_socket_copy(&cai->socket, &peer->socket);
 	cai->adsi = peer->adsi;
 	memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
 	/* Move the calling channel's native codec to the top of the preference list */
@@ -3804,13 +3922,33 @@
 
 static int send_apathetic_reply(unsigned short callno, unsigned short dcallno,
 		struct sockaddr_in *sin, int command, int ts, unsigned char seqno,
-		int sockfd)
-{
-	struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno),
-		.ts = htonl(ts), .iseqno = seqno, .oseqno = 0, .type = AST_FRAME_IAX,
-		.csub = compress_subclass(command) };
-
-	return sendto(sockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin));
+		struct iax2_socket *socket)
+{
+	int res;
+	struct ast_iax2_full_hdr f = {
+		.scallno = htons(0x8000 | callno),
+		.dcallno = htons(dcallno),
+		.ts = htonl(ts),
+		.iseqno = seqno,
+		.oseqno = 0,
+		.type = AST_FRAME_IAX,
+		.csub = compress_subclass(command),
+	};
+
+	switch (socket->type) {
+	case IAX2_SOCKET_TYPE_NONE:
+		ast_log(LOG_WARNING, "Can not send reply without a socket to send on.\n");
+		break;
+	case IAX2_SOCKET_TYPE_UDP:
+		res = sendto(socket->data.sockfd, &f, sizeof(f), 0,
+				(struct sockaddr *) sin, sizeof(*sin));
+		break;
+	case IAX2_SOCKET_TYPE_DTLS:
+		res = ast_dtls_send(socket->data.dtls_handler, &f, sizeof(f), sin);
+		break;
+	}
+
+	return res;
 }
 
 /*!
@@ -3909,10 +4047,12 @@
 	}
 	if (create_addr(pds.peer, c, &sin, &cai)) {
 		ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
+		iax2_socket_cleanup(&cai.socket);
 		return -1;
 	}
 	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");
+		iax2_socket_cleanup(&cai.socket);
 		return -1;
 	}
 	if (!pds.username && !ast_strlen_zero(cai.username))
@@ -4034,7 +4174,8 @@
 		ast_debug(1, "OSP token is undefined\n");
 
 	/* send the command using the appropriate socket for this peer */
-	iaxs[callno]->sockfd = cai.sockfd;
+	iax2_socket_copy(&iaxs[callno]->socket, &cai.socket);
+	iax2_socket_cleanup(&cai.socket);
 
 	/* Add remote vars */
 	if (variablestore) {
@@ -4852,7 +4993,8 @@
 	return ms;
 }
 
-static struct iax2_trunk_peer *find_tpeer(struct sockaddr_in *sin, int fd)
+static struct iax2_trunk_peer *find_tpeer(struct sockaddr_in *sin,
+		struct iax2_socket *socket)
 {
 	struct iax2_trunk_peer *tpeer = NULL;
 	
@@ -4873,9 +5015,12 @@
 			memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
 			tpeer->trunkact = ast_tvnow();
 			ast_mutex_lock(&tpeer->lock);
-			tpeer->sockfd = fd;
+			iax2_socket_copy(&tpeer->socket, socket);
 #ifdef SO_NO_CHECK
-			setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
+			if (tpeer->socket.type == IAX2_SOCKET_TYPE_UDP) {
+				setsockopt(tpeer->socket.data.sockfd, SOL_SOCKET, SO_NO_CHECK,
+						&nochecksums, sizeof(nochecksums));
+			}
 #endif
 			ast_debug(1, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
 			AST_LIST_INSERT_TAIL(&tpeers, tpeer, list);
@@ -4898,7 +5043,7 @@
 	struct ast_iax2_meta_trunk_mini *mtm;
 
 	f = &fr->af;
-	tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
+	tpeer = find_tpeer(&pvt->addr, &pvt->socket);
 	if (tpeer) {
 		if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
 			/* Need to reallocate space */
@@ -6513,23 +6658,38 @@
 	return res;
 }
 
-static int raw_hangup(struct sockaddr_in *sin, unsigned short src, unsigned short dst, int sockfd)
-{
-	struct ast_iax2_full_hdr fh;
-	fh.scallno = htons(src | IAX_FLAG_FULL);
-	fh.dcallno = htons(dst);
-	fh.ts = 0;
-	fh.oseqno = 0;
-	fh.iseqno = 0;
-	fh.type = AST_FRAME_IAX;
-	fh.csub = compress_subclass(IAX_COMMAND_INVAL);
+static int raw_hangup(struct sockaddr_in *sin,
+		unsigned short src, unsigned short dst,
+		struct iax2_socket *socket)
+{
+	int res;
+	struct ast_iax2_full_hdr fh = {
+		.scallno = htons(src | IAX_FLAG_FULL),
+		.dcallno = htons(dst),
+		.type = AST_FRAME_IAX,
+		.csub = compress_subclass(IAX_COMMAND_INVAL),
+	};
+
 	iax_outputframe(NULL, &fh, 0, sin, 0);
-#if 0
-	if (option_debug)
-#endif	
-		ast_debug(1, "Raw Hangup %s:%d, src=%d, dst=%d\n",
-			ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
-	return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
+
+	ast_debug(1, "Raw Hangup %s:%d, src=%d, dst=%d\n",
+			ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
+			src, dst);
+
+	switch (socket->type) {
+	case IAX2_SOCKET_TYPE_NONE:
+		ast_log(LOG_WARNING, "Can not send INVAL without a socket\n");
+		break;
+	case IAX2_SOCKET_TYPE_UDP:
+		res = sendto(socket->data.sockfd, &fh, sizeof(fh), 0,
+				(struct sockaddr *) sin, sizeof(*sin));
+		break;
+	case IAX2_SOCKET_TYPE_DTLS:
+		res = ast_dtls_send(socket->data.dtls_handler, &fh, sizeof(&fh), sin);
+		break;
+	}
+
+	return res;
 }
 
 static void merge_encryption(struct chan_iax2_pvt *p, unsigned int enc)
@@ -7420,7 +7580,8 @@
  * \note Since this function calls send_command_final(), the pvt struct for
  *       the given call number may disappear while executing this function.
  */
-static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh)
+static int update_registry(struct sockaddr_in *sin, int callno, char *devtype,
+		struct iax2_socket *socket, unsigned short refresh)
 {
 	/* Called from IAX thread only, with proper iaxsl lock */
 	struct iax_ie_data ied;
@@ -7487,8 +7648,9 @@
 		goto return_unref;
 	}
 
-	/* Store socket fd */
-	p->sockfd = fd;
+	/* Store socket */
+	iax2_socket_copy(&p->socket, socket);
+
 	/* Setup the expiry */
 	if (p->expire > -1) {
 		if (!ast_sched_thread_del(sched, p->expire)) {
@@ -7825,7 +7987,7 @@
 		/* Any appropriate call will do */
 		fr->data = fr->afdata;
 		fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
-		res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
+		res = transmit_trunk(fr, &tpeer->addr, &tpeer->socket);
 		calls = tpeer->calls;
 #if 0
 		ast_debug(1, "Trunking %d call chunks in %d bytes to %s:%d, ts=%d\n", calls, fr->datalen, ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), ntohl(mth->ts));
@@ -8051,7 +8213,8 @@
 	return -1;
 }
 
-static int check_provisioning(struct sockaddr_in *sin, int sockfd, char *si, unsigned int ver)
+static int check_provisioning(struct sockaddr_in *sin, struct iax2_socket *socket,
+		char *si, unsigned int ver)
 {
 	unsigned int ourver;
 	char rsi[80];
@@ -8060,7 +8223,7 @@
 		return 0;
 	ast_debug(1, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
 	if (ourver != ver) 
-		iax2_provision(sin, sockfd, NULL, rsi, 1);
+		iax2_provision(sin, socket, NULL, rsi, 1);
 	return 0;
 }
 
@@ -8239,13 +8402,93 @@
 	ast_mutex_unlock(&to_here->lock);
 }
 
+static void iax2_thread_process(struct iax2_thread *thread)
+{
+	struct ast_iax2_full_hdr *fh;
+
+	if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
+		thread->iostate = IAX_IOSTATE_IDLE;
+		signal_condition(&thread->lock, &thread->cond);
+		return;
+	}
+
+	/* Determine if this frame is a full frame; if so, and any thread is currently
+	   processing a full frame for the same callno from this peer, then drop this
+	   frame (and the peer will retransmit it) */
+	fh = (struct ast_iax2_full_hdr *) thread->buf;
+	if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
+		struct iax2_thread *cur = NULL;
+		uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
+
+		AST_LIST_LOCK(&active_list);
+		AST_LIST_TRAVERSE(&active_list, cur, list) {
+			if ((cur->ffinfo.callno == callno) &&
+			    !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
+				break;
+		}
+		if (cur) {
+			/* we found another thread processing a full frame for this call,
+			   so queue it up for processing later. */
+			defer_full_frame(thread, cur);
+			AST_LIST_UNLOCK(&active_list);
+			thread->iostate = IAX_IOSTATE_IDLE;
+			signal_condition(&thread->lock, &thread->cond);
+			return;
+		} else {
+			/* this thread is going to process this frame, so mark it */
+			thread->ffinfo.callno = callno;
+			memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
+			thread->ffinfo.type = fh->type;
+			thread->ffinfo.csub = fh->csub;
+		}
+		AST_LIST_UNLOCK(&active_list);
+	}
+
+	/* Mark as ready and send on its way */
+	thread->iostate = IAX_IOSTATE_READY;
+#ifdef DEBUG_SCHED_MULTITHREAD
+	ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
+#endif
+	signal_condition(&thread->lock, &thread->cond);
+}
+
+static void dtls_recv(const struct sockaddr_in *sin_remote, const void *buf,
+		size_t len, void *data)
+{
+	struct iax2_thread *thread;
+	union iax2_socket_data socket_data = {
+		.dtls_handler = data,
+	};
+
+	if (!(thread = find_idle_thread())) {
+		time_t t;
+		static time_t last_errtime = 0;
+		time(&t);
+		if (t != last_errtime) {
+			ast_debug(1, "Out of idle IAX2 threads for I/O, pausing!\n");
+		}
+		last_errtime = t;
+		return;
+	}
+
+	iax2_socket_set_type(&thread->socket, IAX2_SOCKET_TYPE_DTLS, socket_data);
+
+	thread->buf_len = MIN(len, sizeof(thread->readbuf));
+	memcpy(thread->readbuf, buf, thread->buf_len);
+	thread->buf = thread->readbuf;
+
+	iax2_thread_process(thread);
+}
+
 static int socket_read(int *id, int fd, short events, void *cbdata)
 {
 	struct iax2_thread *thread;
 	socklen_t len;
 	time_t t;
 	static time_t last_errtime = 0;
-	struct ast_iax2_full_hdr *fh;
+	union iax2_socket_data socket_data = {
+		.sockfd = fd,
+	};
 
 	if (!(thread = find_idle_thread())) {
 		time(&t);
@@ -8257,7 +8500,7 @@
 	}
 
 	len = sizeof(thread->iosin);
-	thread->iofd = fd;
+	iax2_socket_set_type(&thread->socket, IAX2_SOCKET_TYPE_UDP, socket_data);
 	thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
 	thread->buf_size = sizeof(thread->readbuf);
 	thread->buf = thread->readbuf;
@@ -8269,56 +8512,15 @@
 		signal_condition(&thread->lock, &thread->cond);
 		return 1;
 	}
-	if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
-		thread->iostate = IAX_IOSTATE_IDLE;
-		signal_condition(&thread->lock, &thread->cond);
-		return 1;
-	}
-	
-	/* Determine if this frame is a full frame; if so, and any thread is currently
-	   processing a full frame for the same callno from this peer, then drop this
-	   frame (and the peer will retransmit it) */
-	fh = (struct ast_iax2_full_hdr *) thread->buf;
-	if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
-		struct iax2_thread *cur = NULL;
-		uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
-		
-		AST_LIST_LOCK(&active_list);
-		AST_LIST_TRAVERSE(&active_list, cur, list) {
-			if ((cur->ffinfo.callno == callno) &&
-			    !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
-				break;
-		}
-		if (cur) {
-			/* we found another thread processing a full frame for this call,
-			   so queue it up for processing later. */
-			defer_full_frame(thread, cur);
-			AST_LIST_UNLOCK(&active_list);
-			thread->iostate = IAX_IOSTATE_IDLE;
-			signal_condition(&thread->lock, &thread->cond);
-			return 1;
-		} else {
-			/* this thread is going to process this frame, so mark it */
-			thread->ffinfo.callno = callno;
-			memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
-			thread->ffinfo.type = fh->type;
-			thread->ffinfo.csub = fh->csub;
-		}
-		AST_LIST_UNLOCK(&active_list);
-	}
-	
-	/* Mark as ready and send on its way */
-	thread->iostate = IAX_IOSTATE_READY;
-#ifdef DEBUG_SCHED_MULTITHREAD
-	ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
-#endif
-	signal_condition(&thread->lock, &thread->cond);
+
+	iax2_thread_process(thread);
 
 	return 1;
 }
 
-static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, struct sockaddr_in *sin, int sockfd,
-	struct iax_frame *fr)
+static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta,
+		struct sockaddr_in *sin, struct iax2_socket *socket,
+		struct iax_frame *fr)
 {
 	unsigned char metatype;
 	struct ast_iax2_meta_trunk_mini *mtm;
@@ -8349,7 +8551,7 @@
 	metatype = meta->cmddata;
 	packet_len -= (sizeof(*meta) + sizeof(*mth));
 	ptr = mth->data;
-	tpeer = find_tpeer(sin, sockfd);
+	tpeer = find_tpeer(sin, socket);
 	if (!tpeer) {
 		ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", 
 			ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
@@ -8385,7 +8587,8 @@
 		/* Stop if we don't have enough data */
 		if (len > packet_len)
 			break;
-		fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0, sin, NEW_PREVENT, sockfd, 0);
+		fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0,
+				sin, NEW_PREVENT, socket, 0);
 		if (!fr->callno)
 			continue;
 
@@ -8561,7 +8764,7 @@
 	struct iax_ies ies;
 	struct iax_ie_data ied0, ied1;
 	int format;
-	int fd;
+	struct iax2_socket *socket;
 	int exists;
 	int minivid = 0;
 	char empty[32]="";		/* Safety measure */
@@ -8578,7 +8781,7 @@
 
 	/* Copy frequently used parameters to the stack */
 	res = thread->buf_len;
-	fd = thread->iofd;
+	socket = &thread->socket;
 	memcpy(&sin, &thread->iosin, sizeof(sin));
 
 	if (res < sizeof(*mh)) {
@@ -8592,10 +8795,11 @@
 		}
 
 		/* This is a video frame, get call number */
-		fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0);
+		fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno,
+				&sin, new, socket, 0);
 		minivid = 1;
 	} else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000))
-		return socket_process_meta(res, meta, &sin, fd, fr);
+		return socket_process_meta(res, meta, &sin, socket, fr);
 
 #ifdef DEBUG_SUPPORT
 	if (res >= sizeof(*fh))
@@ -8620,7 +8824,9 @@
 		/* 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, ntohl(fh->ts), fh->iseqno + 1, fd);
+			send_apathetic_reply(1, ntohs(fh->scallno), &sin,
+					IAX_COMMAND_PONG, ntohl(fh->ts),
+					fh->iseqno + 1, socket);
 			return 1;
 		} else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) {
 			/* Ignore */
@@ -8656,7 +8862,8 @@
 			check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1;
 		}
 
-		fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno);
+		fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL,
+				dcallno, &sin, new, socket, check_dcallno);
 	}
 
 	if (fr->callno > 0)
@@ -8671,9 +8878,10 @@
 				 (f.subclass != IAX_COMMAND_TXCNT) &&
 				 (f.subclass != IAX_COMMAND_TXACC) &&
 				 (f.subclass != IAX_COMMAND_FWDOWNL))||
-			    (f.frametype != AST_FRAME_IAX))
+			    (f.frametype != AST_FRAME_IAX)) {
 				raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL,
-				fd);
+						socket);
+			}
 		}
 		if (fr->callno > 0) 
 			ast_mutex_unlock(&iaxsl[fr->callno]);
@@ -9086,7 +9294,7 @@
 					break;
 				if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) {
 					ast_mutex_unlock(&iaxsl[fr->callno]);
-					check_provisioning(&sin, fd, ies.serviceident, ies.provver);
+					check_provisioning(&sin, socket, ies.serviceident, ies.provver);
 					ast_mutex_lock(&iaxsl[fr->callno]);
 					if (!iaxs[fr->callno]) {
 						ast_mutex_unlock(&iaxsl[fr->callno]);
@@ -9851,7 +10059,7 @@
 
 					if (f.subclass == IAX_COMMAND_REGREL)
 						memset(&sin, 0, sizeof(sin));
-					if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh))
+					if (update_registry(&sin, fr->callno, ies.devicetype, socket, ies.refresh))
 						ast_log(LOG_WARNING, "Registry error\n");
 					if (!iaxs[fr->callno]) {
 						ast_mutex_unlock(&iaxsl[fr->callno]);
@@ -9859,7 +10067,7 @@
 					}
 					if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) {
 						ast_mutex_unlock(&iaxsl[fr->callno]);
-						check_provisioning(&sin, fd, ies.serviceident, ies.provver);
+						check_provisioning(&sin, socket, ies.serviceident, ies.provver);
 						ast_mutex_lock(&iaxsl[fr->callno]);
 						if (!iaxs[fr->callno]) {
 							ast_mutex_unlock(&iaxsl[fr->callno]);
@@ -10187,6 +10395,7 @@
 	ast_cond_destroy(&thread->cond);
 	ast_mutex_destroy(&thread->init_lock);
 	ast_cond_destroy(&thread->init_cond);
+	iax2_socket_cleanup(&thread->socket);
 	ast_free(thread);
 	ast_atomic_dec_and_test(&iaxactivethreadcount);
 }
@@ -10353,8 +10562,14 @@
 	}
 
 	if (!reg->callno) {
+		struct iax2_socket default_socket;
+		union iax2_socket_data socket_data = {
+			.sockfd = defaultsockfd,
+		};
+		iax2_socket_set_type(&default_socket, IAX2_SOCKET_TYPE_UDP, socket_data);
 		ast_debug(3, "Allocate call number\n");
-		reg->callno = find_callno_locked(0, 0, &reg->addr, NEW_FORCE, defaultsockfd, 0);
+		reg->callno = find_callno_locked(0, 0, &reg->addr, NEW_FORCE,
+				&default_socket, 0);
 		if (reg->callno < 1) {
 			ast_log(LOG_WARNING, "Unable to create call for registration\n");
 			return -1;
@@ -10375,7 +10590,8 @@
 	return 0;
 }
 
-static int iax2_provision(struct sockaddr_in *end, int sockfd, const char *dest, const char *template, int force)
+static int iax2_provision(struct sockaddr_in *end, struct iax2_socket *socket,
+		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 */
@@ -10397,17 +10613,23 @@
 
 	if (end) {
 		memcpy(&sin, end, sizeof(sin));
-		cai.sockfd = sockfd;
-	} else if (create_addr(dest, NULL, &sin, &cai))
+		iax2_socket_copy(&cai.socket, socket);
+	} else if (create_addr(dest, NULL, &sin, &cai)) {
+		iax2_socket_cleanup(&cai.socket);
 		return -1;
+	}
 
 	/* Build the rest of the message */
 	memset(&ied, 0, sizeof(ied));
 	iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
 
-	callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
-	if (!callno)
+	callno = find_callno_locked(0, 0, &sin, NEW_FORCE, &cai.socket, 0);
+	if (!callno) {
+		iax2_socket_cleanup(&cai.socket);
 		return -1;
+	}
+
+	iax2_socket_cleanup(&cai.socket);
 
 	if (iaxs[callno]) {
 		/* Schedule autodestruct in case they don't ever give us anything back */
@@ -10449,7 +10671,8 @@
 		ast_log(LOG_NOTICE, "Can't provision something with no IP?\n");
 		return -1;
 	}
-	res = iax2_provision(&iaxs[callno]->addr, iaxs[callno]->sockfd, NULL, sdata, force);
+	res = iax2_provision(&iaxs[callno]->addr, &iaxs[callno]->socket, NULL,
+			sdata, force);
 	ast_verb(3, "Provisioned IAXY at '%s' with '%s'= %d\n",
 		ast_inet_ntoa(iaxs[callno]->addr.sin_addr),
 		sdata, res);
@@ -10485,7 +10708,7 @@
 		else
 			return CLI_SHOWUSAGE;
 	}
-	res = iax2_provision(NULL, -1, a->argv[2], a->argv[3], force);
+	res = iax2_provision(NULL, NULL, a->argv[2], a->argv[3], force);
 	if (res < 0)
 		ast_cli(a->fd, "Unable to find peer/address '%s'\n", a->argv[2]);
 	else if (res < 1)
@@ -10561,7 +10784,8 @@
 	}
 	if (heldcall)
 		ast_mutex_unlock(&iaxsl[heldcall]);
-	callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
+	callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE,
+			&peer->socket, 0);
 	if (heldcall)
 		ast_mutex_lock(&iaxsl[heldcall]);
 	if (peer->callno < 1) {
@@ -10638,18 +10862,22 @@
 	/* Populate our address from the given */
 	if (create_addr(pds.peer, NULL, &sin, &cai)) {
 		*cause = AST_CAUSE_UNREGISTERED;
+		iax2_socket_cleanup(&cai.socket);
 		return NULL;
 	}
 
 	if (pds.port)
 		sin.sin_port = htons(atoi(pds.port));
 
-	callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
+	callno = find_callno_locked(0, 0, &sin, NEW_FORCE, &cai.socket, 0);
 	if (callno < 1) {
 		ast_log(LOG_WARNING, "Unable to create call\n");
 		*cause = AST_CAUSE_CONGESTION;
+		iax2_socket_cleanup(&cai.socket);
 		return NULL;
 	}
+
+	iax2_socket_cleanup(&cai.socket);
 
 	/* If this is a trunk, update it now */
 	ast_copy_flags64(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
@@ -10789,10 +11017,17 @@
 	struct sockaddr_in sin;
 	int nonlocal = 1;
 	int port = IAX_DEFAULT_PORTNO;
-	int sockfd = defaultsockfd;
 	char *tmp;
 	char *addr;
 	char *portstr;
+	struct iax2_socket socket = {
+		.type = IAX2_SOCKET_TYPE_NONE,
+	};
+	union iax2_socket_data socket_data = {
+		.sockfd = defaultsockfd,
+	};
+
+	iax2_socket_set_type(&socket, IAX2_SOCKET_TYPE_UDP, socket_data);
 
 	if (!(tmp = ast_strdupa(srcaddr)))
 		return -1;
@@ -10819,7 +11054,7 @@
 			if (!(sock = ast_netsock_find(netsock, &sin)))
 				sock = ast_netsock_find(outsock, &sin);
 			if (sock) {
-				sockfd = ast_netsock_sockfd(sock);
+				socket.data.sockfd = ast_netsock_sockfd(sock);
 				nonlocal = 0;
 			} else {
 				unsigned int orig_saddr = sin.sin_addr.s_addr;
@@ -10829,7 +11064,7 @@
 					sin.sin_addr.s_addr = orig_saddr;
 					sock = ast_netsock_bind(outsock, io, srcaddr, port, qos.tos, qos.cos, socket_read, NULL);
 					if (sock) {
-						sockfd = ast_netsock_sockfd(sock);
+						socket.data.sockfd = ast_netsock_sockfd(sock);
 						ast_netsock_unref(sock);
 						nonlocal = 0;
 					} else {
@@ -10839,8 +11074,8 @@
 			}
 		}
 	}
-		
-	peer->sockfd = sockfd;
+
+	iax2_socket_copy(&peer->socket, &socket);
 
 	if (nonlocal == 1) {
 		ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
@@ -10878,6 +11113,8 @@
 		ast_event_unsubscribe(peer->mwi_event_sub);
 
 	ast_string_field_free_memory(peer);
+
+	iax2_socket_cleanup(&peer->socket);
 }
 
 /*! \brief Create peer structure based on configuration */
@@ -10906,16 +11143,22 @@
 		}
 		unlink_peer(peer);
 	} else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) {
+		union iax2_socket_data socket_data = {
+			.sockfd = defaultsockfd,
+		};
 		peer->expire = -1;
 		peer->pokeexpire = -1;
-		peer->sockfd = defaultsockfd;
+		iax2_socket_set_type(&peer->socket, IAX2_SOCKET_TYPE_UDP, socket_data);
 		if (ast_string_field_init(peer, 32))
 			peer = peer_unref(peer);
 	}
 
 	if (peer) {
 		if (firstpass) {
-			ast_copy_flags64(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+			ast_copy_flags64(peer, &globalflags, IAX_USEJITTERBUF |
+					IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE |
+					IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT |
+					IAX_DTLS);
 			peer->encmethods = iax2_encryption;
 			peer->adsi = adsi;
 			ast_string_field_set(peer,secret,"");
@@ -11102,6 +11345,8 @@
 				} else {
 					ast_clear_flag64(peer, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
 				}
+			} else if (!strcasecmp(v->name, "usedtls")) {
+				ast_set2_flag64(peer, ast_true(v->value), IAX_DTLS);
 			}/* else if (strcasecmp(v->name,"type")) */
 			/*	ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
 			v = v->next;
@@ -11496,6 +11741,7 @@
 	struct iax2_peer *peer;
 	struct ast_netsock *ns;
 	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+	unsigned int dtls_enabled;
 #if 0
 	static unsigned short int last_port=0;
 #endif
@@ -11567,8 +11813,12 @@
 		if (ast_str2cos(tosval, &qos.cos))
 			ast_log(LOG_WARNING, "Invalid cos value, refer to QoS documentation\n");
 	}
-	while(v) {
-		if (!strcasecmp(v->name, "bindport")){ 
+	for (; v; v = v->next) {
+		if (!ast_dtls_config_parse(dtls_data.config, v->name, v->value)) {
+			continue;
+		} else if (!strcasecmp(v->name, "usedtls")) {
+			ast_set2_flag64(&globalflags, ast_true(v->value), IAX_DTLS);
+		} else if (!strcasecmp(v->name, "bindport")) {
 			if (reload)
 				ast_log(LOG_NOTICE, "Ignoring bindport on reload\n");
 			else
@@ -11796,7 +12046,6 @@
 			}
 		} /*else if (strcasecmp(v->name,"type")) */
 		/*	ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
-		v = v->next;
 	}
 	
 	if (defaultsockfd < 0) {
@@ -11908,6 +12157,19 @@
 		cat = ast_category_browse(cfg, cat);
 	}
 	ast_config_destroy(cfg);
+
+	dtls_enabled = ast_dtls_config_get_enabled(dtls_data.config);
+	if (dtls_enabled && !dtls_data.handler) {
+		dtls_data.handler = ast_dtls_handler_alloc(dtls_data.config,
+					dtls_recv, dtls_data.handler);
+		if (!dtls_data.handler) {
+			ast_log(LOG_ERROR, "Failed to start DTLS handler for IAX2\n");
+		}
+	}
+	if (!dtls_enabled && dtls_data.handler) {
+		dtls_data.handler = ast_dtls_handler_unref(dtls_data.handler);
+	}
+
 	return 1;
 }
 
@@ -12008,17 +12270,21 @@
 	}
 
 	/* Populate our address from the given */
-	if (create_addr(pds.peer, NULL, &sin, &cai))
+	if (create_addr(pds.peer, NULL, &sin, &cai)) {
+		iax2_socket_cleanup(&cai.socket);
 		return -1;
+	}
 
 	ast_debug(1, "peer: %s, username: %s, password: %s, context: %s\n",
 		pds.peer, pds.username, pds.password, pds.context);
 
-	callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
+	callno = find_callno_locked(0, 0, &sin, NEW_FORCE, &cai.socket, 0);
 	if (callno < 1) {
 		ast_log(LOG_WARNING, "Unable to create call\n");
 		return -1;
 	}
+
+	iax2_socket_cleanup(&cai.socket);
 
 	ast_string_field_set(iaxs[callno], dproot, data);
 	iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
@@ -12675,6 +12941,13 @@
 	}
 	transmit_processor = ast_taskprocessor_unreference(transmit_processor);
 
+	if (dtls_data.config) {
+		dtls_data.config = ast_dtls_config_unref(dtls_data.config);
+	}
+	if (dtls_data.handler) {
+		dtls_data.handler = ast_dtls_config_unref(dtls_data.handler);
+	}
+
 	con = ast_context_find(regcontext);
 	if (con)
 		ast_context_destroy(con, "IAX2");
@@ -12692,9 +12965,18 @@
 static int peer_set_sock_cb(void *obj, void *arg, int flags)
 {
 	struct iax2_peer *peer = obj;
-
-	if (peer->sockfd < 0)
-		peer->sockfd = defaultsockfd;
+	union iax2_socket_data data;
+
+	if (ast_test_flag64(peer, IAX_DTLS) && dtls_data.handler) {
+		data.dtls_handler = dtls_data.handler;
+		iax2_socket_set_type(&peer->socket, IAX2_SOCKET_TYPE_DTLS, data);
+		return 0;
+	}
+
+	if (peer->socket.data.sockfd < 0) {
+		data.sockfd = defaultsockfd;
+		iax2_socket_set_type(&peer->socket, IAX2_SOCKET_TYPE_UDP, data);
+	}
 
 	return 0;
 }
@@ -12817,6 +13099,8 @@
 	}
 	ast_netsock_init(outsock);
 
+	dtls_data.config = ast_dtls_config_alloc();
+
 	ast_cli_register_multiple(cli_iax2, ARRAY_LEN(cli_iax2));
 
 	ast_register_application_xml(papp, iax2_prov_app);

Modified: team/russell/dtls/configs/iax.conf.sample
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/dtls/configs/iax.conf.sample?view=diff&rev=207354&r1=207353&r2=207354
==============================================================================
--- team/russell/dtls/configs/iax.conf.sample (original)
+++ team/russell/dtls/configs/iax.conf.sample Sun Jul 19 21:27:32 2009
@@ -19,6 +19,84 @@
 ;                               ; addresses, but the first will be the
 ;                               ; default
 ;
+
+; --------------------- DTLS Settings -----------------------------------------
+;
+; How to create a Certificate Authority and generate certificates:
+;
+;     The OpenVPN project provides a nice set of scripts that makes
+; this process very easy to do.  If you're not familiar with managing
+; a certificate authority and creating client and server SSL certificates
+; with OpenSSL, using the scripts from OpenVPN is an easy way to get started.
+;
+; 1) Download OpenVPN.
+;    $ tar -xvzf openvpn-2.0.9.tar.gz
+;    $ cd openvpn-2.0.9/easy-rsa/
+;
+; The rest of this is just a condensed version of what you can get from the
+; OpenVPN documentation.  For more details, see:
+;    -> http://openvpn.net/index.php/open-source/documentation/howto.html#pki
+;
+; 2) Initialize
+;    $ . ./vars
+;    $ ./clean-all
+;
+; 3) Create the CA.  This will ask you to fill in some fields.
+;    $ ./build-ca
+;
+; 4) Create server certificate.
+;    $ ./build-key-server server
+;
+; 5) Generate Diffie Hellman parameters:
+;    $ ./build-dh
+;
+; 6) Copy your new files to where Asterisk can find them.
+;    $ cd keys
+;    $ sudo cp ca.crt dh1024.pem server.crt server.key \
+;        /var/lib/asterisk/keys
+;
+; --- DTLS Configuration Options ---
+;
+; Enable DTLS.  This turns on the ability to accept DTLS connections.
+; Note that this is required for making DTLS client connections, as well.
+; By default, this is off.
+;
+;dtlsenable = yes
+
+;
+; This option turns on using DTLS for client connections.  This may be
+; specified globally or per-peer.
+; By default, this is off.
+;
+;usedtls=yes
+
+;
+; Certificate Authority (CA) certificate (optional)
+;
+;dtlscafile = /var/lib/asterisk/keys/ca.crt
+
+;
+; Path to directory of CA certs (optional)
+;
+;dtlscapath = /var/lib/asterisk/ca
+
+;
+; Server private key (required)
+;
+;dtlsprivatekey = /var/lib/asterisk/keys/server.key
+
+;
+; Server certificate (required)
+;
+;dtlscertfile = /var/lib/asterisk/keys/server.crt
+
+;
+; DH Params (required)
+;

[... 8 lines stripped ...]



More information about the asterisk-commits mailing list