From 96d09ce0ad7dc878561b8d4c909a162941e666ce Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Fri, 1 Mar 2019 15:25:07 +0100
Subject: [PATCH] Bonjour: Fix: Set Query ID to zero, no ID checking in
 responses. Fix #1864

---
 src/slic3r/Utils/Bonjour.cpp | 45 +++++++++++++-----------------------
 1 file changed, 16 insertions(+), 29 deletions(-)

diff --git a/src/slic3r/Utils/Bonjour.cpp b/src/slic3r/Utils/Bonjour.cpp
index bfd9d4828..4953cfc64 100644
--- a/src/slic3r/Utils/Bonjour.cpp
+++ b/src/slic3r/Utils/Bonjour.cpp
@@ -5,7 +5,6 @@
 #include <array>
 #include <vector>
 #include <string>
-#include <random>
 #include <thread>
 #include <boost/optional.hpp>
 #include <boost/system/error_code.hpp>
@@ -34,6 +33,9 @@ namespace Slic3r {
 // the implementations has been tested with AFL.
 
 
+// Relevant RFC: https://www.ietf.org/rfc/rfc6762.txt
+
+
 struct DnsName: public std::string
 {
 	enum
@@ -387,7 +389,7 @@ struct DnsMessage
 
 	DnsSDMap sdmap;
 
-	static optional<DnsMessage> decode(const std::vector<char> &buffer, optional<uint16_t> id_wanted = boost::none)
+	static optional<DnsMessage> decode(const std::vector<char> &buffer)
 	{
 		const auto size = buffer.size();
 		if (size < DnsHeader::SIZE + DnsQuestion::MIN_SIZE || size > MAX_SIZE) {
@@ -397,10 +399,6 @@ struct DnsMessage
 		DnsMessage res;
 		res.header = DnsHeader::decode(buffer);
 
-		if (id_wanted && *id_wanted != res.header.id) {
-			return boost::none;
-		}
-
 		if (res.header.qdcount > 1 || res.header.ancount > MAX_ANS) {
 			return boost::none;
 		}
@@ -472,16 +470,12 @@ struct BonjourRequest
 	static const asio::ip::address_v4 MCAST_IP4;
 	static const uint16_t MCAST_PORT;
 
-	uint16_t id;
 	std::vector<char> data;
 
 	static optional<BonjourRequest> make(const std::string &service, const std::string &protocol);
 
 private:
-	BonjourRequest(uint16_t id, std::vector<char> &&data) :
-		id(id),
-		data(std::move(data))
-	{}
+	BonjourRequest(std::vector<char> &&data) : data(std::move(data)) {}
 };
 
 const asio::ip::address_v4 BonjourRequest::MCAST_IP4{0xe00000fb};
@@ -493,22 +487,15 @@ optional<BonjourRequest> BonjourRequest::make(const std::string &service, const
 		return boost::none;
 	}
 
-	std::random_device dev;
-	std::uniform_int_distribution<uint16_t> dist;
-	uint16_t id = dist(dev);
-	uint16_t id_big = endian::native_to_big(id);
-	const char *id_char = reinterpret_cast<char*>(&id_big);
-
 	std::vector<char> data;
 	data.reserve(service.size() + 18);
 
-	// Add the transaction ID
-	data.push_back(id_char[0]);
-	data.push_back(id_char[1]);
-
 	// Add metadata
 	static const unsigned char rq_meta[] = {
-		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+		0x00, 0x00, // Query ID (zero for mDNS)
+		0x00, 0x00, // Flags
+		0x00, 0x01, // One query
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // Zero Answer, Authority, and Additional RRs
 	};
 	std::copy(rq_meta, rq_meta + sizeof(rq_meta), std::back_inserter(data));
 
@@ -522,11 +509,14 @@ optional<BonjourRequest> BonjourRequest::make(const std::string &service, const
 
 	// Add the rest of PTR record
 	static const unsigned char ptr_tail[] = {
-		0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0xff,
+		0x05, // length of "label"
+		0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, // "label" string and terminator
+		0x00, 0x0c, // Type PTR
+		0x00, 0xff, // Class ANY
 	};
 	std::copy(ptr_tail, ptr_tail + sizeof(ptr_tail), std::back_inserter(data));
 
-	return BonjourRequest(id, std::move(data));
+	return BonjourRequest(std::move(data));
 }
 
 
@@ -539,7 +529,6 @@ struct Bonjour::priv
 	const std::string service_dn;
 	unsigned timeout;
 	unsigned retries;
-	uint16_t rq_id;
 
 	std::vector<char> buffer;
 	std::thread io_thread;
@@ -558,8 +547,7 @@ Bonjour::priv::priv(std::string service, std::string protocol) :
 	protocol(std::move(protocol)),
 	service_dn((boost::format("_%1%._%2%.local") % this->service % this->protocol).str()),
 	timeout(10),
-	retries(1),
-	rq_id(0)
+	retries(1)
 {
 	buffer.resize(DnsMessage::MAX_SIZE);
 }
@@ -585,7 +573,7 @@ void Bonjour::priv::udp_receive(udp::endpoint from, size_t bytes)
 	}
 
 	buffer.resize(bytes);
-	const auto dns_msg = DnsMessage::decode(buffer, rq_id);
+	const auto dns_msg = DnsMessage::decode(buffer);
 	if (dns_msg) {
 		asio::ip::address ip = from.address();
 		if (dns_msg->rr_a) { ip = dns_msg->rr_a->ip; }
@@ -629,7 +617,6 @@ void Bonjour::priv::lookup_perform()
 	}
 
 	auto self = this;
-	rq_id = brq->id;
 
 	try {
 		boost::asio::io_service io_service;