[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, ®->addr, NEW_FORCE, defaultsockfd, 0);
+ reg->callno = find_callno_locked(0, 0, ®->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