diff -Naurp asterisk-1.8.5.0.orig/res/res_stun_monitor.c asterisk-1.8.5.0.patched/res/res_stun_monitor.c
--- asterisk-1.8.5.0.orig/res/res_stun_monitor.c	2010-10-11 23:38:39.000000000 +0200
+++ asterisk-1.8.5.0.patched/res/res_stun_monitor.c	2011-08-23 20:47:49.000000000 +0200
@@ -44,42 +44,19 @@ static struct ast_sched_thread *sched;
 static struct {
 	struct sockaddr_in stunaddr;      /*!< The stun address we send requests to*/
 	struct sockaddr_in externaladdr;  /*!< current perceived external address. */
+	struct ast_sockaddr dst;
+	unsigned int local_port;          /*!< Local port to bind to in network byte order.*/
 	ast_mutex_t lock;
 	unsigned int refresh;
-	int stunsock;
 	unsigned int monitor_enabled:1;
 	unsigned int externaladdr_known:1;
 } args;
 
-static inline void stun_close_sock(void)
+static inline void stun_cleanup(void)
 {
-	if (args.stunsock != -1) {
-		close(args.stunsock);
-		args.stunsock = -1;
-		memset(&args.externaladdr, 0, sizeof(args.externaladdr));
-		args.externaladdr_known = 0;
-	}
-}
-
-/* \brief purge the stun socket's receive buffer before issuing a new request
- *
- * XXX Note that this is somewhat of a hack.  This function is essentially doing
- * a cleanup on the socket rec buffer to handle removing any STUN responses we have not
- * handled.  This is called before sending out a new STUN request so we don't read
- * a latent previous response thinking it is new.
- */
-static void stun_purge_socket(void)
-{
-	int flags = fcntl(args.stunsock, F_GETFL);
-	int res = 0;
-	unsigned char reply_buf[1024];
-
-	fcntl(args.stunsock, F_SETFL, flags | O_NONBLOCK);
-	while (res != -1) {
-		/* throw away everything in the buffer until we reach the end. */
-		res = recv(args.stunsock, reply_buf, sizeof(reply_buf), 0);
-	}
-	fcntl(args.stunsock, F_SETFL, flags & ~O_NONBLOCK);
+	memset(&args.externaladdr, 0, sizeof(args.externaladdr));
+	args.externaladdr_known = 0;
+	args.local_port = 0;
 }
 
 /* \brief called by scheduler to send STUN request */
@@ -88,18 +65,53 @@ static int stun_monitor_request(const vo
 	int res;
 	int generate_event = 0;
 	struct sockaddr_in answer = { 0, };
+	struct sockaddr_in tmp;
+	struct ast_sockaddr bnd;
+	int stunsock;
 
-
-	/* once the stun socket goes away, this scheduler item will go away as well */
 	ast_mutex_lock(&args.lock);
-	if (args.stunsock == -1) {
-		ast_log(LOG_ERROR, "STUN monitor: can not send STUN request, socket is not open\n");
+
+	/* Create socket */
+	if ( (stunsock = socket(PF_INET,SOCK_DGRAM, 0)) < 0 )
+	{
+		ast_log(LOG_WARNING, "Unable to create STUN socket: %s\n", strerror(errno));
 		goto monitor_request_cleanup;
 	}
 
-	stun_purge_socket();
+	/* Bind socket */
+	if (args.local_port) {
+		memset(&tmp, 0, sizeof(tmp));
+		tmp.sin_family = AF_INET;
+		tmp.sin_port = args.local_port;
+		ast_sockaddr_from_sin(&bnd,&tmp);
+
+		if (ast_bind(stunsock, &bnd) != 0)
+		{
+			ast_log(LOG_WARNING, "Unable to bind STUN socket: %s\n", strerror(errno));
+			goto monitor_request_cleanup;
+		}
+	}
 
-	if (!(ast_stun_request(args.stunsock, &args.stunaddr, NULL, &answer)) &&
+	/* Connect socket to target */
+	if (ast_connect(stunsock, &args.dst) != 0)
+	{
+		ast_log(LOG_WARNING, "SIP STUN Failed to connect to %s\n", ast_sockaddr_stringify(&args.dst));
+		goto monitor_request_cleanup;
+	}
+
+	/* Store local socket */
+	if (!args.local_port)
+	{
+		if (ast_getsockname(stunsock, &bnd) != 0)
+		{
+			ast_log(LOG_WARNING, "Cannot get SIP STUN local port: %s\n",strerror(errno));
+			goto monitor_request_cleanup;
+		}
+		ast_sockaddr_to_sin(&bnd,&tmp);
+		args.local_port = tmp.sin_port;
+	}
+
+	if (!(ast_stun_request(stunsock, &args.stunaddr, NULL, &answer)) &&
 		(memcmp(&args.externaladdr, &answer, sizeof(args.externaladdr)))) {
 		const char *newaddr = ast_strdupa(ast_inet_ntoa(answer.sin_addr));
 		int newport = ntohs(answer.sin_port);
@@ -138,6 +150,10 @@ static int stun_monitor_request(const vo
 monitor_request_cleanup:
 	/* always refresh this scheduler item.  It will be removed elsewhere when
 	 * it is supposed to go away */
+	if (stunsock >= 0)
+	{
+		close(stunsock);
+	}
 	res = args.refresh * 1000;
 	ast_mutex_unlock(&args.lock);
 
@@ -153,9 +169,7 @@ static void stun_stop_monitor(void)
 		sched = ast_sched_thread_destroy(sched);
 		ast_log(LOG_NOTICE, "STUN monitor stopped\n");
 	}
-	/* it is only safe to destroy the socket without holding arg->lock
-	 * after the sched thread is destroyed */
-	stun_close_sock();
+	stun_cleanup();
 }
 
 /* \brief starts the stun monitor thread
@@ -163,25 +177,11 @@ static void stun_stop_monitor(void)
  */
 static int stun_start_monitor(void)
 {
-	struct ast_sockaddr dst;
-	/* clean up any previous open socket */
-	stun_close_sock();
+	/* clean up any previous old data */
+	stun_cleanup();
 
 	/* create destination ast_sockaddr */
-	ast_sockaddr_from_sin(&dst, &args.stunaddr);
-
-	/* open new socket binding */
-	args.stunsock = socket(AF_INET, SOCK_DGRAM, 0);
-	if (args.stunsock < 0) {
-		ast_log(LOG_WARNING, "Unable to create STUN socket: %s\n", strerror(errno));
-		return -1;
-	}
-
-	if (ast_connect(args.stunsock, &dst) != 0) {
-		ast_log(LOG_WARNING, "SIP STUN Failed to connect to %s\n", ast_sockaddr_stringify(&dst));
-		stun_close_sock();
-		return -1;
-	}
+	ast_sockaddr_from_sin(&args.dst, &args.stunaddr);
 
 	/* if scheduler thread is not started, make sure to start it now */
 	if (sched) {
@@ -190,14 +190,14 @@ static int stun_start_monitor(void)
 
 	if (!(sched = ast_sched_thread_create())) {
 		ast_log(LOG_ERROR, "Failed to create stun monitor scheduler thread\n");
-		stun_close_sock();
+		stun_cleanup();
 		return -1;
 	}
 
 	if (ast_sched_thread_add_variable(sched, (args.refresh * 1000), stun_monitor_request, NULL, 1) < 0) {
 		ast_log(LOG_ERROR, "Unable to schedule STUN network monitor \n");
 		sched = ast_sched_thread_destroy(sched);
-		stun_close_sock();
+		stun_cleanup();
 		return -1;
 	}
 
@@ -289,7 +289,6 @@ static int unload_module(void)
 static int load_module(void)
 {
 	ast_mutex_init(&args.lock);
-	args.stunsock = -1;
 	memset(&args.externaladdr, 0, sizeof(args.externaladdr));
 	args.externaladdr_known = 0;
 	sched = NULL;
