From 490971e8e5bffb1094ca6b5740df4c1c6e3659ef Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 5 Jun 2019 20:30:54 +0200 Subject: [PATCH 1/3] mcproxy: fix block/filtering code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mcproxy supports a generic filtering/blacklisting mechanism but it’s currently broken. In the case of routed video (e.g. mcproxy routing video from WAN -> LAN), it will forward multicast between the LAN and WAN. There are perfectly valid use cases for this like reporting but other less-appropriate things like mDNS and SSDP leak through from LAN -> WAN which is bad. Signed-off-by: Sukru Senli Signed-off-by: Chad Monroe Signed-off-by: John Crispin --- mcproxy/files/mcproxy.config | 8 ++ .../patches/0005-fix-match-filter-calls.patch | 46 ++++++++ mcproxy/patches/0006-block-ingress.patch | 104 ++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 mcproxy/patches/0005-fix-match-filter-calls.patch create mode 100644 mcproxy/patches/0006-block-ingress.patch diff --git a/mcproxy/files/mcproxy.config b/mcproxy/files/mcproxy.config index 10cc410..e80b602 100644 --- a/mcproxy/files/mcproxy.config +++ b/mcproxy/files/mcproxy.config @@ -229,3 +229,11 @@ config behaviour option direction 'out' option whitelist '1' option table '{(*|*)}' + +config blocks + # mDNS + list entries '(*|239.255.255.0/24)' + # SSDP + list entries '(*|224.0.0.0/24)' + # SLP + list entries '(*|239.192.0.0/16)' diff --git a/mcproxy/patches/0005-fix-match-filter-calls.patch b/mcproxy/patches/0005-fix-match-filter-calls.patch new file mode 100644 index 0000000..c6956e0 --- /dev/null +++ b/mcproxy/patches/0005-fix-match-filter-calls.patch @@ -0,0 +1,46 @@ +--- a/mcproxy/src/proxy/simple_mc_proxy_routing.cpp ++++ b/mcproxy/src/proxy/simple_mc_proxy_routing.cpp +@@ -118,13 +118,13 @@ void interface_memberships::process_upst + for (auto source_it = cs.first.m_source_list.begin(); source_it != cs.first.m_source_list.end();) { + + //downstream out +- if (!cs.second->match_output_filter(interfaces::get_if_name(upstr_e.m_if_index), gaddr, source_it->saddr)) { ++ if (!cs.second->match_output_filter(interfaces::get_if_name(upstr_e.m_if_index), source_it->saddr, gaddr)) { + source_it = cs.first.m_source_list.erase(source_it); + continue; + } + + //upstream in +- if (!upstr_e.m_interface->match_input_filter(interfaces::get_if_name(upstr_e.m_if_index), gaddr, source_it->saddr)) { ++ if (!upstr_e.m_interface->match_input_filter(interfaces::get_if_name(upstr_e.m_if_index), source_it->saddr, gaddr)) { + tmp_sstate.m_source_list.insert(*source_it); + source_it = cs.first.m_source_list.erase(source_it); + continue; +@@ -175,13 +175,13 @@ void interface_memberships::process_upst + for (auto source_it = cs_it->first.m_source_list.begin(); source_it != cs_it->first.m_source_list.end();) { + + //downstream out +- if (!cs_it->second->match_output_filter(interfaces::get_if_name(upstr_e.m_if_index), gaddr, source_it->saddr)) { ++ if (!cs_it->second->match_output_filter(interfaces::get_if_name(upstr_e.m_if_index), source_it->saddr, gaddr)) { + ++source_it; + continue; + } + + //upstream in +- if (!upstr_e.m_interface->match_input_filter(interfaces::get_if_name(upstr_e.m_if_index), gaddr, source_it->saddr)) { ++ if (!upstr_e.m_interface->match_input_filter(interfaces::get_if_name(upstr_e.m_if_index), source_it->saddr, gaddr)) { + ++source_it; + continue; + } +@@ -619,9 +619,9 @@ bool simple_mc_proxy_routing::check_inte + std::string input_if_index_name = interfaces::get_if_name(input_if_index); + if (!input_if_index_name.empty()) { + if (interface_direction == ID_IN) { +- return interf->match_input_filter(input_if_index_name, gaddr, saddr); ++ return interf->match_input_filter(input_if_index_name, saddr, gaddr); + } else if (interface_direction == ID_OUT) { +- return interf->match_output_filter(input_if_index_name, gaddr, saddr); ++ return interf->match_output_filter(input_if_index_name, saddr, gaddr); + } else { + HC_LOG_ERROR("unkown interface direction"); + return false; diff --git a/mcproxy/patches/0006-block-ingress.patch b/mcproxy/patches/0006-block-ingress.patch new file mode 100644 index 0000000..c8bcdb3 --- /dev/null +++ b/mcproxy/patches/0006-block-ingress.patch @@ -0,0 +1,104 @@ +--- a/mcproxy/src/proxy/proxy_instance.cpp ++++ b/mcproxy/src/proxy/proxy_instance.cpp +@@ -171,6 +171,9 @@ void proxy_instance::worker_thread() + HC_LOG_TRACE(""); + while (m_running) { + auto msg = m_job_queue.dequeue(); ++ ++ HC_LOG_DEBUG("Proxy Message: " << msg->get_message_type_name(msg->get_type()) ); ++ + switch (msg->get_type()) { + case proxy_msg::TEST_MSG: + (*msg)(); +@@ -190,28 +193,80 @@ void proxy_instance::worker_thread() + } else { + HC_LOG_DEBUG("failed to find querier of interface: " << interfaces::get_if_name(std::static_pointer_cast(msg)->get_if_index())); + } +- } ++ } + break; + case proxy_msg::GROUP_RECORD_MSG: { +- auto r = std::static_pointer_cast(msg); ++ auto gr = std::static_pointer_cast(msg); + + if (m_in_debug_testing_mode) { + std::cout << "!!--ACTION: receive record" << std::endl; +- std::cout << *r << std::endl; ++ std::cout << *gr << std::endl; + std::cout << std::endl; + } + +- auto it = m_downstreams.find(r->get_if_index()); ++ auto slist = gr->get_slist(); ++ addr_storage saddr; ++ if ( slist.empty() ) ++ { ++ saddr = "0.0.0.0"; ++ } ++ else ++ { ++ saddr = slist.begin()->saddr; ++ } ++ auto it = m_downstreams.find(gr->get_if_index()); + if (it != std::end(m_downstreams)) { +- it->second.m_querier->receive_record(msg); ++ // Check for input filters ++ if ( ! it->second.m_interface->match_input_filter( interfaces::get_if_name( gr->get_if_index() ), ++ saddr, ++ gr->get_gaddr() ) ++ ) ++ { ++ HC_LOG_DEBUG("group report " << gr->get_gaddr() << " filtered"); ++ } ++ else ++ { ++ it->second.m_querier->receive_record(msg); ++ } + } else { +- HC_LOG_DEBUG("failed to find querier of interface: " << interfaces::get_if_name(std::static_pointer_cast(msg)->get_if_index())); ++ HC_LOG_DEBUG("failed to find querier of interface: " << interfaces::get_if_name( gr->get_if_index() )); + } +- } ++ } ++ break; ++ case proxy_msg::NEW_SOURCE_MSG: { ++ auto sm = std::static_pointer_cast(msg); ++ // Find the interface ++ std::shared_ptr interf; ++ auto it = m_downstreams.find(sm->get_if_index()); ++ if (it != std::end(m_downstreams)) { ++ interf = it->second.m_interface; ++ } else { ++ for (auto & e : m_upstreams) { ++ if (e.m_if_index == sm->get_if_index()) { ++ interf = e.m_interface; ++ break; ++ } ++ } ++ } ++ if ( !interf ) ++ { ++ HC_LOG_DEBUG("failed to find interface: " << interfaces::get_if_name( sm->get_if_index() ) << " for Source message " << sm->get_saddr() << " | " << sm->get_gaddr() ); ++ break; ++ } ++ // Check for input filters ++ if ( ! interf->match_input_filter( interfaces::get_if_name( sm->get_if_index() ), ++ sm->get_saddr(), ++ sm->get_gaddr() ) ++ ) ++ { ++ HC_LOG_DEBUG("source " << sm->get_saddr() << " | " << sm->get_gaddr() << " filtered"); ++ } ++ else ++ { ++ m_routing_management->event_new_source(msg); ++ } ++ } + break; +- case proxy_msg::NEW_SOURCE_MSG: +- m_routing_management->event_new_source(msg); +- break; + case proxy_msg::NEW_SOURCE_TIMER_MSG: + m_routing_management->timer_triggerd_maintain_routing_table(msg); + break; + return false; From a56d996b94682c90729ad9b561168635b857649c Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 5 Jun 2019 20:33:42 +0200 Subject: [PATCH 2/3] mcproxy: add igmpV2 reply support mcproxy has no way to send an IGMPv2 query today. If you force IGMPv2 (by setting the protocol in the mcproxy config and setting the force_igmp_version flag on all interfaces) the bridge will send v2 queries but if mcproxy takes over as the querier it will send v3 queries. The patch below adds support for sending v2 queries so everyone stays in sync: Signed-off-by: Sukru Senli Signed-off-by: Chad Monroe Signed-off-by: John Crispin --- mcproxy/files/mcproxy.config | 2 +- mcproxy/patches/0006-block-ingress.patch | 114 ++++++++++----------- mcproxy/patches/0007-igmpv2-queries.patch | 116 ++++++++++++++++++++++ 3 files changed, 167 insertions(+), 65 deletions(-) create mode 100644 mcproxy/patches/0007-igmpv2-queries.patch diff --git a/mcproxy/files/mcproxy.config b/mcproxy/files/mcproxy.config index e80b602..f028795 100644 --- a/mcproxy/files/mcproxy.config +++ b/mcproxy/files/mcproxy.config @@ -230,7 +230,7 @@ config behaviour option whitelist '1' option table '{(*|*)}' -config blocks +config blocks blocks # mDNS list entries '(*|239.255.255.0/24)' # SSDP diff --git a/mcproxy/patches/0006-block-ingress.patch b/mcproxy/patches/0006-block-ingress.patch index c8bcdb3..5998741 100644 --- a/mcproxy/patches/0006-block-ingress.patch +++ b/mcproxy/patches/0006-block-ingress.patch @@ -1,25 +1,23 @@ ---- a/mcproxy/src/proxy/proxy_instance.cpp -+++ b/mcproxy/src/proxy/proxy_instance.cpp +Index: mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/proxy/proxy_instance.cpp +=================================================================== +--- mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99.orig/mcproxy/src/proxy/proxy_instance.cpp ++++ mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/proxy/proxy_instance.cpp @@ -171,6 +171,9 @@ void proxy_instance::worker_thread() HC_LOG_TRACE(""); while (m_running) { auto msg = m_job_queue.dequeue(); + -+ HC_LOG_DEBUG("Proxy Message: " << msg->get_message_type_name(msg->get_type()) ); ++ HC_LOG_DEBUG("Proxy Message: " << msg->get_message_type_name(msg->get_type()) ); + switch (msg->get_type()) { case proxy_msg::TEST_MSG: (*msg)(); -@@ -190,28 +193,80 @@ void proxy_instance::worker_thread() - } else { - HC_LOG_DEBUG("failed to find querier of interface: " << interfaces::get_if_name(std::static_pointer_cast(msg)->get_if_index())); - } -- } -+ } +@@ -193,25 +196,66 @@ void proxy_instance::worker_thread() + } break; case proxy_msg::GROUP_RECORD_MSG: { - auto r = std::static_pointer_cast(msg); -+ auto gr = std::static_pointer_cast(msg); ++ auto gr = std::static_pointer_cast(msg); if (m_in_debug_testing_mode) { std::cout << "!!--ACTION: receive record" << std::endl; @@ -29,31 +27,25 @@ } - auto it = m_downstreams.find(r->get_if_index()); -+ auto slist = gr->get_slist(); -+ addr_storage saddr; -+ if ( slist.empty() ) -+ { -+ saddr = "0.0.0.0"; -+ } -+ else -+ { -+ saddr = slist.begin()->saddr; -+ } ++ auto slist = gr->get_slist(); ++ addr_storage saddr; ++ if (slist.empty()) { ++ saddr = "0.0.0.0"; ++ } else { ++ saddr = slist.begin()->saddr; ++ } + auto it = m_downstreams.find(gr->get_if_index()); if (it != std::end(m_downstreams)) { - it->second.m_querier->receive_record(msg); -+ // Check for input filters -+ if ( ! it->second.m_interface->match_input_filter( interfaces::get_if_name( gr->get_if_index() ), -+ saddr, -+ gr->get_gaddr() ) -+ ) -+ { -+ HC_LOG_DEBUG("group report " << gr->get_gaddr() << " filtered"); -+ } -+ else -+ { -+ it->second.m_querier->receive_record(msg); -+ } ++ // Check for input filters ++ if (!it->second.m_interface->match_input_filter(interfaces::get_if_name(gr->get_if_index()), saddr, gr->get_gaddr())) ++ { ++ HC_LOG_DEBUG("group report " << gr->get_gaddr() << " filtered"); ++ } ++ else ++ { ++ it->second.m_querier->receive_record(msg); ++ } } else { - HC_LOG_DEBUG("failed to find querier of interface: " << interfaces::get_if_name(std::static_pointer_cast(msg)->get_if_index())); + HC_LOG_DEBUG("failed to find querier of interface: " << interfaces::get_if_name( gr->get_if_index() )); @@ -62,37 +54,32 @@ + } + break; + case proxy_msg::NEW_SOURCE_MSG: { -+ auto sm = std::static_pointer_cast(msg); -+ // Find the interface -+ std::shared_ptr interf; -+ auto it = m_downstreams.find(sm->get_if_index()); -+ if (it != std::end(m_downstreams)) { -+ interf = it->second.m_interface; -+ } else { -+ for (auto & e : m_upstreams) { -+ if (e.m_if_index == sm->get_if_index()) { -+ interf = e.m_interface; -+ break; -+ } -+ } -+ } -+ if ( !interf ) -+ { -+ HC_LOG_DEBUG("failed to find interface: " << interfaces::get_if_name( sm->get_if_index() ) << " for Source message " << sm->get_saddr() << " | " << sm->get_gaddr() ); -+ break; -+ } -+ // Check for input filters -+ if ( ! interf->match_input_filter( interfaces::get_if_name( sm->get_if_index() ), -+ sm->get_saddr(), -+ sm->get_gaddr() ) -+ ) -+ { -+ HC_LOG_DEBUG("source " << sm->get_saddr() << " | " << sm->get_gaddr() << " filtered"); -+ } -+ else -+ { -+ m_routing_management->event_new_source(msg); -+ } ++ auto sm = std::static_pointer_cast(msg); ++ // Find the interface ++ std::shared_ptr interf; ++ auto it = m_downstreams.find(sm->get_if_index()); ++ if (it != std::end(m_downstreams)) { ++ interf = it->second.m_interface; ++ } else { ++ for (auto & e : m_upstreams) { ++ if (e.m_if_index == sm->get_if_index()) { ++ interf = e.m_interface; ++ break; ++ } ++ } ++ } ++ if ( !interf ) ++ { ++ HC_LOG_DEBUG("failed to find interface: " << interfaces::get_if_name( sm->get_if_index() ) << " for Source message " << sm->get_saddr() << " | " << sm->get_gaddr() ); ++ break; ++ } ++ // Check for input filters ++ if (!interf->match_input_filter(interfaces::get_if_name(sm->get_if_index()), sm->get_saddr(), sm->get_gaddr())) ++ { ++ HC_LOG_DEBUG("source " << sm->get_saddr() << " | " << sm->get_gaddr() << " filtered"); ++ } else { ++ m_routing_management->event_new_source(msg); ++ } + } break; - case proxy_msg::NEW_SOURCE_MSG: @@ -101,4 +88,3 @@ case proxy_msg::NEW_SOURCE_TIMER_MSG: m_routing_management->timer_triggerd_maintain_routing_table(msg); break; - return false; diff --git a/mcproxy/patches/0007-igmpv2-queries.patch b/mcproxy/patches/0007-igmpv2-queries.patch new file mode 100644 index 0000000..005b56d --- /dev/null +++ b/mcproxy/patches/0007-igmpv2-queries.patch @@ -0,0 +1,116 @@ +--- a/mcproxy/include/proxy/igmp_sender.hpp ++++ b/mcproxy/include/proxy/igmp_sender.hpp +@@ -37,9 +37,10 @@ class igmp_sender : public sender + { + private: + bool send_igmpv3_query(unsigned int if_index, const timers_values& tv, const addr_storage& gaddr, bool s_flag, const source_list& slist) const; ++ bool send_igmpv2_query(unsigned int if_index, const timers_values& tv, const addr_storage& gaddr ) const; + + public: +- igmp_sender(const std::shared_ptr& interfaces); ++ igmp_sender(const std::shared_ptr& interfaces, const group_mem_protocol gmp); + + bool send_record(unsigned int if_index, mc_filter filter_mode, const addr_storage& gaddr, const source_list& slist) const override; + +--- a/mcproxy/src/proxy/igmp_sender.cpp ++++ b/mcproxy/src/proxy/igmp_sender.cpp +@@ -32,7 +32,7 @@ + + #include + +-igmp_sender::igmp_sender(const std::shared_ptr& interfaces): sender(interfaces, IGMPv3) ++igmp_sender::igmp_sender(const std::shared_ptr& interfaces, const group_mem_protocol gmp): sender(interfaces, gmp) + { + HC_LOG_TRACE(""); + +@@ -119,10 +119,79 @@ bool igmp_sender::send_mc_addr_and_src_s + return rc; + } + ++bool igmp_sender::send_igmpv2_query(unsigned int if_index, const timers_values& tv, const addr_storage& gaddr ) const ++{ ++ HC_LOG_TRACE(""); ++ ++ std::unique_ptr packet; ++ unsigned int size; ++ ++ size = sizeof(ip) + sizeof(router_alert_option) + sizeof(igmp); ++ packet.reset(new unsigned char[size]); ++ ++ addr_storage dst_addr; ++ ++ if (gaddr == addr_storage(AF_INET)) { //is general query ++ dst_addr = IPV4_ALL_HOST_ADDR; ++ } else { ++ dst_addr = gaddr; ++ } ++ ++ //------------------------------------------------------------------- ++ //fill ip header ++ ip* ip_hdr = reinterpret_cast(packet.get()); ++ ++ ip_hdr->ip_v = 4; ++ ip_hdr->ip_hl = (sizeof(ip) + sizeof(router_alert_option)) / 4; ++ ip_hdr->ip_tos = 0; ++ ip_hdr->ip_len = htons(size); ++ ip_hdr->ip_id = 0; ++ ip_hdr->ip_off = htons(0 | IP_DF); //dont fragment flag ++ ip_hdr->ip_ttl = 1; ++ ip_hdr->ip_p = IPPROTO_IGMP; ++ ip_hdr->ip_sum = 0; ++ ip_hdr->ip_src = m_interfaces->get_saddr(interfaces::get_if_name(if_index)).get_in_addr(); ++ ip_hdr->ip_dst = dst_addr.get_in_addr(); ++ ++ //------------------------------------------------------------------- ++ //fill router_alert_option header ++ router_alert_option* ra_hdr = reinterpret_cast(reinterpret_cast(ip_hdr) + sizeof(ip)); ++ *ra_hdr = router_alert_option(); ++ ++ ip_hdr->ip_sum = m_sock.calc_checksum(reinterpret_cast(ip_hdr), sizeof(ip) + sizeof(router_alert_option)); ++ ++ //------------------------------------------------------------------- ++ //fill igmpv3 query ++ igmp* query = reinterpret_cast(reinterpret_cast(ra_hdr) + sizeof(router_alert_option)); ++ ++ query->igmp_type = IGMP_MEMBERSHIP_QUERY; ++ ++ if (gaddr == addr_storage(AF_INET)) { //general query ++ query->igmp_code = tv.maxrespi_to_maxrespc_igmpv3(tv.get_query_response_interval()); ++ } else { ++ query->igmp_code = tv.maxrespi_to_maxrespc_igmpv3(tv.get_last_listener_query_time()); ++ } ++ ++ query->igmp_cksum = 0; ++ query->igmp_group = gaddr.get_in_addr(); ++ ++ query->igmp_cksum = m_sock.calc_checksum(reinterpret_cast(query), (sizeof(igmp) )); ++ ++ if (!m_sock.choose_if(if_index)) { ++ return false; ++ } ++ ++ return m_sock.send_packet(dst_addr, reinterpret_cast(ip_hdr), size); ++} ++ + bool igmp_sender::send_igmpv3_query(unsigned int if_index, const timers_values& tv, const addr_storage& gaddr, bool s_flag, const source_list& slist) const + { + HC_LOG_TRACE(""); + ++ if ( (m_group_mem_protocol & IGMPv3) == 0 ) { ++ return send_igmpv2_query( if_index, tv, gaddr ); ++ } ++ + std::unique_ptr packet; + unsigned int size; + +--- a/mcproxy/src/proxy/proxy_instance.cpp ++++ b/mcproxy/src/proxy/proxy_instance.cpp +@@ -119,7 +119,7 @@ bool proxy_instance::init_sender() + { + HC_LOG_TRACE(""); + if (is_IPv4(m_group_mem_protocol)) { +- m_sender = std::make_shared(m_interfaces); ++ m_sender = std::make_shared(m_interfaces, m_group_mem_protocol ); + } else if (is_IPv6(m_group_mem_protocol)) { + m_sender = std::make_shared(m_interfaces); + } else { From ff7c509caa61e41b4a740c30384cf3290124d9bd Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 30 Jun 2019 13:03:23 +0200 Subject: [PATCH 3/3] mcproxy: fix up sourcefilter patch this spewed out 2 compile warnings In file included from build_dir/target-mipsel_24kc_musl/mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/mc_socket.cpp:43:0: build_dir/target-mipsel_24kc_musl/mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/sourcefilter.cpp: In function 'int setsourcefilter(int, uint32_t, const sockaddr*, socklen_t, uint32_t, uint32_t, const sockaddr_storage*)': build_dir/target-mipsel_24kc_musl/mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/sourcefilter.cpp:157:3: warning: this 'else' clause does not guard... [-Wmisleading-indentation] else ^~~~ build_dir/target-mipsel_24kc_musl/mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/sourcefilter.cpp:160:5: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'else' int save_errno = errno; ^~~ Signed-off-by: John Crispin --- mcproxy/patches/0003-add-sourcefilter.patch | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mcproxy/patches/0003-add-sourcefilter.patch b/mcproxy/patches/0003-add-sourcefilter.patch index 2f64975..cf67411 100644 --- a/mcproxy/patches/0003-add-sourcefilter.patch +++ b/mcproxy/patches/0003-add-sourcefilter.patch @@ -1,5 +1,7 @@ ---- a/mcproxy/src/utils/mc_socket.cpp -+++ b/mcproxy/src/utils/mc_socket.cpp +Index: mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/mc_socket.cpp +=================================================================== +--- mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99.orig/mcproxy/src/utils/mc_socket.cpp ++++ mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/mc_socket.cpp @@ -37,6 +37,10 @@ #include #include @@ -11,8 +13,10 @@ std::string ipAddrResolver(std::string ipAddr) { std::string str[][2] = { +Index: mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/sourcefilter.cpp +=================================================================== --- /dev/null -+++ b/mcproxy/src/utils/sourcefilter.cpp ++++ mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/sourcefilter.cpp @@ -0,0 +1,165 @@ +/* Get source filter. Linux version. + Copyright (C) 2004-2014 Free Software Foundation, Inc. @@ -173,9 +177,9 @@ + else + result = setsockopt (s, sol, MCAST_MSFILTER, gf, needed); + -+ int save_errno = errno; -+ free (gf); -+ errno = save_errno; ++ int save_errno = errno; ++ free (gf); ++ errno = save_errno; + + return result; +}