diff --git a/docs/manual.html b/docs/manual.html
index 50dcd0a06..ccaf1f8bf 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -2458,6 +2458,7 @@ struct session_settings
int inactivity_timeout;
bool use_dht_as_fallback;
bool free_torrent_hashes;
+ bool upnp_ignore_nonrouters;
};
user_agent this is the client identification to the tracker.
@@ -2565,6 +2566,10 @@ needed anymore since the torrent won't download anything more). If it's set
to false they are not freed. If they are freed, the torrent_info returned
by get_torrent_info() will return an object that may be incomplete, that
cannot be passed back to add_torrent() for instance.
+upnp_ignore_nonrouters indicates whether or not the UPnP implementation
+should ignore any broadcast response from a device whose address is not the
+configured router for this machine. i.e. it's a way to not talk to other
+people's routers by mistake.
diff --git a/docs/manual.rst b/docs/manual.rst
index 001f9fd5f..d3b60188b 100644
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -2446,6 +2446,7 @@ that will be sent to the tracker. The user-agent is a good way to identify your
int inactivity_timeout;
bool use_dht_as_fallback;
bool free_torrent_hashes;
+ bool upnp_ignore_nonrouters;
};
``user_agent`` this is the client identification to the tracker.
@@ -2578,6 +2579,11 @@ to false they are not freed. If they are freed, the torrent_info_ returned
by get_torrent_info() will return an object that may be incomplete, that
cannot be passed back to `add_torrent()`_ for instance.
+``upnp_ignore_nonrouters`` indicates whether or not the UPnP implementation
+should ignore any broadcast response from a device whose address is not the
+configured router for this machine. i.e. it's a way to not talk to other
+people's routers by mistake.
+
pe_settings
===========
diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp
index 7cc7d26da..2817d27d2 100644
--- a/include/libtorrent/session_settings.hpp
+++ b/include/libtorrent/session_settings.hpp
@@ -117,6 +117,7 @@ namespace libtorrent
, use_dht_as_fallback(true)
#endif
, free_torrent_hashes(true)
+ , upnp_ignore_nonrouters(true)
{}
// this is the user agent that will be sent to the tracker
@@ -292,6 +293,11 @@ namespace libtorrent
// make the get_torrent_info() function to return an incomplete
// torrent object that cannot be passed back to add_torrent()
bool free_torrent_hashes;
+
+ // when this is true, the upnp port mapper will ignore
+ // any upnp devices that don't have an address that matches
+ // our currently configured router.
+ bool upnp_ignore_nonrouters;
};
#ifndef TORRENT_DISABLE_DHT
diff --git a/include/libtorrent/upnp.hpp b/include/libtorrent/upnp.hpp
index 442d7aa4a..5f35616ca 100644
--- a/include/libtorrent/upnp.hpp
+++ b/include/libtorrent/upnp.hpp
@@ -68,7 +68,7 @@ class upnp : public intrusive_ptr_base
public:
upnp(io_service& ios, connection_queue& cc
, address const& listen_interface, std::string const& user_agent
- , portmap_callback_t const& cb);
+ , portmap_callback_t const& cb, bool ignore_nonrouters);
~upnp();
// maps the ports, if a port is set to 0
@@ -242,6 +242,8 @@ private:
std::string m_model;
+ std::vector m_filter;
+
#ifdef TORRENT_UPNP_LOGGING
std::ofstream m_log;
#endif
diff --git a/src/session_impl.cpp b/src/session_impl.cpp
index 6f0013c63..e2d4b8ef4 100755
--- a/src/session_impl.cpp
+++ b/src/session_impl.cpp
@@ -2339,7 +2339,8 @@ namespace detail
, m_listen_interface.address()
, m_settings.user_agent
, bind(&session_impl::on_port_mapping
- , this, _1, _2, _3));
+ , this, _1, _2, _3)
+ , m_settings.upnp_ignore_nonrouters);
m_upnp->discover_device();
m_upnp->set_mappings(m_listen_interface.port(),
diff --git a/src/upnp.cpp b/src/upnp.cpp
index 064b6550d..23a8d01a6 100644
--- a/src/upnp.cpp
+++ b/src/upnp.cpp
@@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/xml_parse.hpp"
#include "libtorrent/connection_queue.hpp"
+#include "libtorrent/enum_net.hpp"
#include
#include
@@ -61,7 +62,7 @@ namespace libtorrent
upnp::upnp(io_service& ios, connection_queue& cc
, address const& listen_interface, std::string const& user_agent
- , portmap_callback_t const& cb)
+ , portmap_callback_t const& cb, bool ignore_nonrouters)
: m_udp_local_port(0)
, m_tcp_local_port(0)
, m_user_agent(user_agent)
@@ -81,6 +82,21 @@ upnp::upnp(io_service& ios, connection_queue& cc
m_log.open("upnp.log", std::ios::in | std::ios::out | std::ios::trunc);
#endif
m_retry_count = 0;
+
+ if (ignore_nonrouters)
+ {
+ asio::error_code ec;
+ std::vector const& net = enum_net_interfaces(m_io_service, ec);
+ m_filter.reserve(net.size());
+ for (std::vector::const_iterator i = net.begin()
+ , end(net.end()); i != end; ++i)
+ {
+ asio::error_code e;
+ address a = router_for_interface(*i, e);
+ if (e || is_loopback(a)) continue;
+ m_filter.push_back(a);
+ }
+ }
}
upnp::~upnp()
@@ -249,6 +265,18 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0
*/
+ if (!m_filter.empty() && std::find(m_filter.begin(), m_filter.end()
+ , from.address()) == m_filter.end())
+ {
+ // this upnp device is filtered because it's not in the
+ // list of configured routers
+#ifdef TORRENT_UPNP_LOGGING
+ m_log << time_now_string() << " <== (" << from << ") Rootdevice "
+ "ignored because it's not out router" << std::endl;
+#endif
+ return;
+ }
+
http_parser p;
bool error = false;
p.incoming(buffer::const_interval(buffer
diff --git a/test/test_upnp.cpp b/test/test_upnp.cpp
index 78828491c..f8f7e4b86 100644
--- a/test/test_upnp.cpp
+++ b/test/test_upnp.cpp
@@ -24,7 +24,7 @@ int main(int argc, char* argv[])
}
connection_queue cc(ios);
- boost::intrusive_ptr upnp_handler = new upnp(ios, cc, address_v4(), user_agent, &callback);
+ boost::intrusive_ptr upnp_handler = new upnp(ios, cc, address_v4(), user_agent, &callback, true);
upnp_handler->discover_device();
deadline_timer timer(ios);