}
pos += 1;
- uint16_t qtype = (const unsigned char)packet[pos]*256 + (const unsigned char)packet[pos+1];
+ uint16_t qtype = (reinterpret_cast<const unsigned char*>(packet)[pos])*256 + reinterpret_cast<const unsigned char*>(packet)[pos+1];
pos += DNS_TYPE_SIZE;
pos += DNS_CLASS_SIZE;
generateEDNSOption(EDNSOptionCode::ECS, payload, res);
}
-void generateOptRR(const std::string& optRData, string& res, uint16_t udpPayloadSize, bool dnssecOK)
+void generateOptRR(const std::string& optRData, string& res, uint16_t udpPayloadSize, uint8_t ednsrcode, bool dnssecOK)
{
const uint8_t name = 0;
dnsrecordheader dh;
EDNS0Record edns0;
- edns0.extRCode = 0;
+ edns0.extRCode = ednsrcode;
edns0.version = 0;
edns0.extFlags = dnssecOK ? htons(EDNS_HEADER_FLAG_DO) : 0;
dh.d_class = htons(udpPayloadSize);
static_assert(sizeof(EDNS0Record) == sizeof(dh.d_ttl), "sizeof(EDNS0Record) must match sizeof(dnsrecordheader.d_ttl)");
memcpy(&dh.d_ttl, &edns0, sizeof edns0);
- dh.d_clen = htons((uint16_t) optRData.length());
+ dh.d_clen = htons(static_cast<uint16_t>(optRData.length()));
res.reserve(sizeof(name) + sizeof(dh) + optRData.length());
- res.assign((const char *) &name, sizeof name);
- res.append((const char *) &dh, sizeof dh);
+ res.assign(reinterpret_cast<const char *>(&name), sizeof name);
+ res.append(reinterpret_cast<const char *>(&dh), sizeof(dh));
res.append(optRData.c_str(), optRData.length());
}
/* we need to add a EDNS0 RR with one EDNS0 ECS option, fixing the AR count */
string EDNSRR;
struct dnsheader* dh = reinterpret_cast<struct dnsheader*>(packet);
- generateOptRR(newECSOption, EDNSRR, g_EdnsUDPPayloadSize, false);
+ generateOptRR(newECSOption, EDNSRR, g_EdnsUDPPayloadSize, 0, false);
/* does it fit in the existing buffer? */
if (packetSize - *len <= EDNSRR.size()) {
int removeEDNSOptionFromOPT(char* optStart, size_t* optLen, const uint16_t optionCodeToRemove)
{
- /* we need at least:
- root label (1), type (2), class (2), ttl (4) + rdlen (2)*/
- if (*optLen < 11) {
+ if (*optLen < optRecordMinimumSize) {
return EINVAL;
}
const unsigned char* end = (const unsigned char*) optStart + *optLen;
bool isEDNSOptionInOpt(const std::string& packet, const size_t optStart, const size_t optLen, const uint16_t optionCodeToFind, size_t* optContentStart, uint16_t* optContentLen)
{
- /* we need at least:
- root label (1), type (2), class (2), ttl (4) + rdlen (2)*/
- if (optLen < 11) {
+ if (optLen < optRecordMinimumSize) {
return false;
}
size_t p = optStart + 9;
- uint16_t rdLen = (0x100*packet.at(p) + packet.at(p+1));
+ uint16_t rdLen = (0x100*static_cast<unsigned char>(packet.at(p)) + static_cast<unsigned char>(packet.at(p+1)));
p += sizeof(rdLen);
- if (rdLen > (optLen - 11)) {
+ if (rdLen > (optLen - optRecordMinimumSize)) {
return false;
}
size_t rdEnd = p + rdLen;
while ((p + 4) <= rdEnd) {
- const uint16_t optionCode = 0x100*packet.at(p) + packet.at(p+1);
+ const uint16_t optionCode = 0x100*static_cast<unsigned char>(packet.at(p)) + static_cast<unsigned char>(packet.at(p+1));
p += sizeof(optionCode);
- const uint16_t optionLen = 0x100*packet.at(p) + packet.at(p+1);
+ const uint16_t optionLen = 0x100*static_cast<unsigned char>(packet.at(p)) + static_cast<unsigned char>(packet.at(p+1));
p += sizeof(optionLen);
if ((p + optionLen) > rdEnd) {
return 0;
}
-bool addEDNS(dnsheader* dh, uint16_t& len, const size_t size, bool dnssecOK, uint16_t payloadSize)
+bool addEDNS(dnsheader* dh, uint16_t& len, const size_t size, bool dnssecOK, uint16_t payloadSize, uint8_t ednsrcode)
{
if (dh->arcount != 0) {
return false;
}
std::string optRecord;
- generateOptRR(std::string(), optRecord, payloadSize, dnssecOK);
+ generateOptRR(std::string(), optRecord, payloadSize, ednsrcode, dnssecOK);
if (optRecord.size() >= size || (size - optRecord.size()) < len) {
return false;
char* optRDLen = reinterpret_cast<char*>(dq.dh) + optRDPosition;
char * optPtr = (optRDLen - (/* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE + /* Z */ 2));
- const uint8_t* zPtr = (const uint8_t*) optPtr + /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE;
+ const uint8_t* zPtr = reinterpret_cast<const uint8_t*>(optPtr) + /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE;
uint16_t z = 0x100 * (*zPtr) + *(zPtr + 1);
bool dnssecOK = z & EDNS_HEADER_FLAG_DO;
if (g_addEDNSToSelfGeneratedResponses) {
/* now we need to add a new OPT record */
- return addEDNS(dq.dh, dq.len, dq.size, dnssecOK, g_PayloadSizeSelfGenAnswers);
+ return addEDNS(dq.dh, dq.len, dq.size, dnssecOK, g_PayloadSizeSelfGenAnswers, dq.ednsRCode);
}
/* otherwise we are just fine */
pos++;
- uint16_t qtype = (const unsigned char)packet[pos]*256 + (const unsigned char)packet[pos+1];
+ uint16_t qtype = (reinterpret_cast<const unsigned char*>(packet)[pos])*256 + reinterpret_cast<const unsigned char*>(packet)[pos+1];
pos += DNS_TYPE_SIZE;
pos += DNS_CLASS_SIZE;
return 0;
}
- const uint8_t* z = (const uint8_t*) packet + pos + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE;
+ const uint8_t* z = reinterpret_cast<const uint8_t*>(packet) + pos + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE;
return 0x100 * (*z) + *(z+1);
}
catch(...)
return false;
}
+
+bool getEDNS0Record(const DNSQuestion& dq, EDNS0Record& edns0)
+{
+ uint16_t optStart;
+ size_t optLen = 0;
+ bool last = false;
+ const char * packet = reinterpret_cast<const char*>(dq.dh);
+ std::string packetStr(packet, dq.len);
+ int res = locateEDNSOptRR(packetStr, &optStart, &optLen, &last);
+ if (res != 0) {
+ // no EDNS OPT RR
+ return false;
+ }
+
+ if (optLen < optRecordMinimumSize) {
+ return false;
+ }
+
+ if (optStart < dq.len && packetStr.at(optStart) != 0) {
+ // OPT RR Name != '.'
+ return false;
+ }
+
+ static_assert(sizeof(EDNS0Record) == sizeof(uint32_t), "sizeof(EDNS0Record) must match sizeof(uint32_t) AKA RR TTL size");
+ // copy out 4-byte "ttl" (really the EDNS0 record), after root label (1) + type (2) + class (2).
+ memcpy(&edns0, packet + optStart + 5, sizeof edns0);
+ return true;
+}