return ENOENT;
}
+void generateEDNSOption(uint16_t optionCode, const std::string& payload, std::string& res)
+{
+ const uint16_t ecsOptionCode = htons(optionCode);
+ const uint16_t payloadLen = htons(payload.length());
+ res.append((const char *) &ecsOptionCode, sizeof ecsOptionCode);
+ res.append((const char *) &payloadLen, sizeof payloadLen);
+ res.append(payload);
+}
+
static void generateECSOption(const ComboAddress& source, string& res)
{
- const uint16_t ecsOptionCode = htons(EDNS0_OPTION_CODE_ECS);
Netmask sourceNetmask(source, source.sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6);
EDNSSubnetOpts ecsOpts;
ecsOpts.source = sourceNetmask;
string payload = makeEDNSSubnetOptsString(ecsOpts);
- const uint16_t payloadLen = htons(payload.length());
- res.append((const char *) &ecsOptionCode, sizeof ecsOptionCode);
- res.append((const char *) &payloadLen, sizeof payloadLen);
- res.append(payload);
+ generateEDNSOption(EDNS0_OPTION_CODE_ECS, payload, res);
}
-static void generateECSOptRR(const ComboAddress& source, string & res)
+void generateOptRR(const std::string& optRData, string& res)
{
const uint8_t name = 0;
dnsrecordheader dh;
dh.d_type = htons(QType::OPT);
dh.d_class = htons(q_EdnsUDPPayloadSize);
memcpy(&dh.d_ttl, &edns0, sizeof edns0);
- string optRData;
- generateECSOption(source, optRData);
dh.d_clen = htons((uint16_t) optRData.length());
res.assign((const char *) &name, sizeof name);
res.append((const char *) &dh, sizeof dh);
/* we need to add a EDNS0 RR with one EDNS0 ECS option, fixing the AR count */
string EDNSRR;
struct dnsheader* dh = (struct dnsheader*) packet;
- generateECSOptRR(remote, EDNSRR);
+ string optRData;
+ generateECSOption(remote, optRData);
+ generateOptRR(optRData, EDNSRR);
uint16_t arcount = ntohs(dh->arcount);
arcount++;
dh->arcount = htons(arcount);
int rewriteResponseWithoutEDNS(const char * packet, size_t len, vector<uint8_t>& newContent);
int locateEDNSOptRR(const char * packet, size_t len, const char ** optStart, size_t * optLen, bool * last);
void handleEDNSClientSubnet(char * packet, size_t packetSize, unsigned int consumed, uint16_t * len, string& largerPacket, bool * ednsAdded, const ComboAddress& remote);
+void generateOptRR(const std::string& optRData, string& res);
+void generateEDNSOption(uint16_t optionCode, const std::string& payload, std::string& res);
#include "dnsdist.hh"
+#include "dnsdist-ecs.hh"
#include "dnsname.hh"
#include "dolog.hh"
if(dq->dh->arcount)
return Action::None;
- char* dest = ((char*)dq->dh) + dq->len;
- dnsrecordheader dh;
- EDNS0Record edns0;
- edns0.extRCode = 0;
- edns0.version = 0;
- edns0.Z = 0;
-
- dh.d_type = htons(QType::OPT);
- dh.d_class = htons(1500);
- memcpy(&dh.d_ttl, &edns0, sizeof edns0);
+ string mac = getMACAddress(*dq->remote);
+ if(mac.empty())
+ return Action::None;
+
string optRData;
- const uint16_t optionCode=htons(d_code), optionLen=htons(6);
- optRData.append((const char*)&optionCode, 2);
- optRData.append((const char*)&optionLen, 2);
- string mac=getMACAddress(*dq->remote);
- if(!mac.empty()) {
- dq->dh->arcount=ntohs(1);
- optRData.append(mac);
- dh.d_clen = htons((uint16_t) optRData.length());
- uint8_t name=0;
- string res((const char *) &name, sizeof name);
- res.append((const char *) &dh, sizeof dh);
- res.append(optRData.c_str(), optRData.length());
- memcpy(dest, res.c_str(), res.length());
- dq->len+=res.length();
- }
+ generateEDNSOption(d_code, mac, optRData);
+
+ string res;
+ generateOptRR(optRData, res);
+
+ if ((dq->size - dq->len) < res.length())
+ return Action::None;
+
+ dq->dh->arcount = htons(1);
+ char* dest = ((char*)dq->dh) + dq->len;
+ memcpy(dest, res.c_str(), res.length());
+ dq->len += res.length();
+
return Action::None;
}
string toString() const override