From d78f7f92b2afa033ff959e84bf164454ca9a5de8 Mon Sep 17 00:00:00 2001 From: Joshua Colp Date: Thu, 4 Oct 2012 13:49:45 +0000 Subject: Add support for applying direct media ACLs between differing channel technologies. Review: https://reviewboard.asterisk.org/r/2122/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@374414 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 85 +++++++++++++------------------------------ include/asterisk/rtp_engine.h | 6 +-- main/rtp_engine.c | 26 +++++++------ 3 files changed, 41 insertions(+), 76 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 8e071e11d..b938d2d81 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -31867,25 +31867,6 @@ static int reload_config(enum channelreloadreason reason) return 0; } -static int apply_directmedia_acl(struct sip_pvt *p, struct ast_acl_list *directmediaacl, const char *op) -{ - struct ast_sockaddr us = { { 0, }, }, them = { { 0, }, }; - int res = AST_SENSE_ALLOW; - - ast_rtp_instance_get_remote_address(p->rtp, &them); - ast_rtp_instance_get_local_address(p->rtp, &us); - - if ((res = ast_apply_acl(directmediaacl, &them, "SIP Direct Media ACL: ")) == AST_SENSE_DENY) { - const char *us_addr = ast_strdupa(ast_sockaddr_stringify(&us)); - const char *them_addr = ast_strdupa(ast_sockaddr_stringify(&them)); - - ast_debug(3, "Reinvite %s to %s denied by directmedia ACL on %s\n", - op, them_addr, us_addr); - } - - return res; -} - static struct ast_udptl *sip_get_udptl_peer(struct ast_channel *chan) { struct sip_pvt *p; @@ -31947,72 +31928,56 @@ static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl) return 0; } -static int sip_allow_anyrtp_remote(struct ast_channel *chan1, struct ast_channel *chan2, char *rtptype) +static int sip_allow_anyrtp_remote(struct ast_channel *chan1, struct ast_rtp_instance *instance, const char *rtptype) { - struct sip_pvt *p1 = NULL, *p2 = NULL; - struct ast_acl_list *p2_directmediaacl = NULL; /* opposed directmediaha for comparing against first channel host address */ - struct ast_acl_list *p1_directmediaacl = NULL; /* opposed directmediaha for comparing against second channel host address */ + struct sip_pvt *p; + struct ast_acl_list *acl = NULL; int res = 1; - if (!(p1 = ast_channel_tech_pvt(chan1))) { + if (!(p = ast_channel_tech_pvt(chan1))) { return 0; } - if (!(p2 = ast_channel_tech_pvt(chan2))) { - return 0; + sip_pvt_lock(p); + if (p->relatedpeer && p->relatedpeer->directmediaacl) { + acl = ast_duplicate_acl_list(p->relatedpeer->directmediaacl); } + sip_pvt_unlock(p); - sip_pvt_lock(p2); - if (p2->relatedpeer && p2->relatedpeer->directmediaacl) { - p2_directmediaacl = ast_duplicate_acl_list(p2->relatedpeer->directmediaacl); + if (!acl) { + return res; } - sip_pvt_unlock(p2); - sip_pvt_lock(p1); - if (p1->relatedpeer && p1->relatedpeer->directmediaacl) { - p1_directmediaacl = ast_duplicate_acl_list(p1->relatedpeer->directmediaacl); - } + if (ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA)) { + struct ast_sockaddr us = { { 0, }, }, them = { { 0, }, }; - if (p2_directmediaacl && ast_test_flag(&p1->flags[0], SIP_DIRECT_MEDIA)) { - if (!apply_directmedia_acl(p1, p2_directmediaacl, rtptype)) { - res = 0; - } - } - sip_pvt_unlock(p1); + ast_rtp_instance_get_remote_address(instance, &them); + ast_rtp_instance_get_local_address(instance, &us); - if (res == 0) { - goto allow_anyrtp_remote_end; - } + if (ast_apply_acl(acl, &them, "SIP Direct Media ACL: ") == AST_SENSE_DENY) { + const char *us_addr = ast_strdupa(ast_sockaddr_stringify(&us)); + const char *them_addr = ast_strdupa(ast_sockaddr_stringify(&them)); + + ast_debug(3, "Reinvite %s to %s denied by directmedia ACL on %s\n", + rtptype, them_addr, us_addr); - sip_pvt_lock(p2); - if (p1_directmediaacl && ast_test_flag(&p2->flags[0], SIP_DIRECT_MEDIA)) { - if (!apply_directmedia_acl(p2, p1_directmediaacl, rtptype)) { res = 0; } } - sip_pvt_unlock(p2); - -allow_anyrtp_remote_end: - - if (p2_directmediaacl) { - p2_directmediaacl = ast_free_acl_list(p2_directmediaacl); - } - if (p1_directmediaacl) { - p1_directmediaacl = ast_free_acl_list(p1_directmediaacl); - } + ast_free_acl_list(acl); return res; } -static int sip_allow_rtp_remote(struct ast_channel *chan1, struct ast_channel *chan2) +static int sip_allow_rtp_remote(struct ast_channel *chan1, struct ast_rtp_instance *instance) { - return sip_allow_anyrtp_remote(chan1, chan2, "audio"); + return sip_allow_anyrtp_remote(chan1, instance, "audio"); } -static int sip_allow_vrtp_remote(struct ast_channel *chan1, struct ast_channel *chan2) +static int sip_allow_vrtp_remote(struct ast_channel *chan1, struct ast_rtp_instance *instance) { - return sip_allow_anyrtp_remote(chan1, chan2, "video"); + return sip_allow_anyrtp_remote(chan1, instance, "video"); } static enum ast_rtp_glue_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance) diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h index 293a7a792..72c162d20 100644 --- a/include/asterisk/rtp_engine.h +++ b/include/asterisk/rtp_engine.h @@ -509,10 +509,9 @@ struct ast_rtp_glue { /*! * \brief Used to prevent two channels from remotely bridging audio rtp if the channel tech has a * reason for prohibiting it based on qualities that need to be compared from both channels. - * \note This function should only be called with two channels of the same technology * \note This function may be NULL for a given channel driver. This should be accounted for and if that is the case, function this is not used. */ - int (*allow_rtp_remote)(struct ast_channel *chan1, struct ast_channel *chan2); + int (*allow_rtp_remote)(struct ast_channel *chan1, struct ast_rtp_instance *instance); /*! * \brief Callback for retrieving the RTP instance carrying video * \note This function increases the reference count on the returned RTP instance. @@ -521,10 +520,9 @@ struct ast_rtp_glue { /*! * \brief Used to prevent two channels from remotely bridging video rtp if the channel tech has a * reason for prohibiting it based on qualities that need to be compared from both channels. - * \note This function should only be called with two channels of the same technology * \note This function may be NULL for a given channel driver. This should be accounted for and if that is the case, this function is not used. */ - int (*allow_vrtp_remote)(struct ast_channel *chan1, struct ast_channel *chan2); + int (*allow_vrtp_remote)(struct ast_channel *chan1, struct ast_rtp_instance *instance); /*! * \brief Callback for retrieving the RTP instance carrying text diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 4bcdb138a..55ca0f2b7 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -1484,19 +1484,21 @@ enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct as audio_glue1_res = glue1->get_rtp_info(c1, &instance1); video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID; - /* If the channels are of the same technology, they might have limitations on remote bridging */ - if (ast_channel_tech(c0) == ast_channel_tech(c1)) { - if (audio_glue0_res == audio_glue1_res && audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) { - if (glue0->allow_rtp_remote && !(glue0->allow_rtp_remote(c0, c1))) { - /* If the allow_rtp_remote indicates that remote isn't allowed, revert to local bridge */ - audio_glue0_res = audio_glue1_res = AST_RTP_GLUE_RESULT_LOCAL; - } + /* Apply any limitations on direct media bridging that may be present */ + if (audio_glue0_res == audio_glue1_res && audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) { + if (glue0->allow_rtp_remote && !(glue0->allow_rtp_remote(c0, instance1))) { + /* If the allow_rtp_remote indicates that remote isn't allowed, revert to local bridge */ + audio_glue0_res = audio_glue1_res = AST_RTP_GLUE_RESULT_LOCAL; + } else if (glue1->allow_rtp_remote && !(glue1->allow_rtp_remote(c1, instance0))) { + audio_glue0_res = audio_glue1_res = AST_RTP_GLUE_RESULT_LOCAL; } - if (video_glue0_res == video_glue1_res && video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) { - if (glue0->allow_vrtp_remote && !(glue0->allow_vrtp_remote(c0, c1))) { - /* if the allow_vrtp_remote indicates that remote isn't allowed, revert to local bridge */ - video_glue0_res = video_glue1_res = AST_RTP_GLUE_RESULT_LOCAL; - } + } + if (video_glue0_res == video_glue1_res && video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) { + if (glue0->allow_vrtp_remote && !(glue0->allow_vrtp_remote(c0, instance1))) { + /* if the allow_vrtp_remote indicates that remote isn't allowed, revert to local bridge */ + video_glue0_res = video_glue1_res = AST_RTP_GLUE_RESULT_LOCAL; + } else if (glue1->allow_vrtp_remote && !(glue1->allow_vrtp_remote(c1, instance0))) { + video_glue0_res = video_glue1_res = AST_RTP_GLUE_RESULT_LOCAL; } } -- cgit v1.2.3