{
dq->dh->rcode = d_rcode;
dq->dh->qr = true; // for good measure
+ setResponseHeadersFromConfig(*dq->dh, d_responseConfig);
return Action::HeaderModify;
}
std::string toString() const override
return "set rcode "+std::to_string(d_rcode);
}
+ ResponseConfig d_responseConfig;
private:
uint8_t d_rcode;
};
dq->dh->rcode = (d_rcode & 0xF);
dq->ednsRCode = ((d_rcode & 0xFFF0) >> 4);
dq->dh->qr = true; // for good measure
+ setResponseHeadersFromConfig(*dq->dh, d_responseConfig);
return Action::HeaderModify;
}
std::string toString() const override
return "set ercode "+ERCode::to_s(d_rcode);
}
+ ResponseConfig d_responseConfig;
private:
uint8_t d_rcode;
};
char* dest = ((char*)dq->dh) + dq->len;
dq->dh->qr = true; // for good measure
- if (d_setAA) {
- dq->dh->aa = *d_setAA;
- }
- if (d_setAD) {
- dq->dh->ad = *d_setAD;
- }
- else {
- dq->dh->ad = false;
- }
- if (d_setRA) {
- dq->dh->ra = *d_setRA;
- }
- else {
- dq->dh->ra = dq->dh->rd; // for good measure
- }
+ setResponseHeadersFromConfig(*dq->dh, d_responseConfig);
dq->dh->ancount = 0;
dq->dh->arcount = 0; // for now, forget about your EDNS, we're marching over it
dq->du->setHTTPResponse(d_code, d_body, d_contentType);
dq->dh->qr = true; // for good measure
+ setResponseHeadersFromConfig(*dq->dh, d_responseConfig);
return Action::HeaderModify;
}
{
return "return an HTTP status of " + std::to_string(d_code);
}
+
+ ResponseConfig d_responseConfig;
private:
std::string d_body;
std::string d_contentType;
});
}
-typedef std::unordered_map<std::string, boost::variant<bool> > spoofparams_t;
+typedef std::unordered_map<std::string, boost::variant<bool> > responseParams_t;
-static void parseSpoofConfig(boost::optional<spoofparams_t> vars, boost::optional<bool>& setAA, boost::optional<bool>& setAD, boost::optional<bool>& setRA)
+static void parseResponseConfig(boost::optional<responseParams_t> vars, ResponseConfig& config)
{
if (vars) {
if (vars->count("aa")) {
- setAA = boost::get<bool>((*vars)["aa"]);
+ config.setAA = boost::get<bool>((*vars)["aa"]);
}
if (vars->count("ad")) {
- setAD = boost::get<bool>((*vars)["ad"]);
+ config.setAD = boost::get<bool>((*vars)["ad"]);
}
if (vars->count("ra")) {
- setRA = boost::get<bool>((*vars)["ra"]);
+ config.setRA = boost::get<bool>((*vars)["ra"]);
}
}
}
+void setResponseHeadersFromConfig(dnsheader& dh, const ResponseConfig& config)
+{
+ if (config.setAA) {
+ dh.aa = *config.setAA;
+ }
+ if (config.setAD) {
+ dh.ad = *config.setAD;
+ }
+ else {
+ dh.ad = false;
+ }
+ if (config.setRA) {
+ dh.ra = *config.setRA;
+ }
+ else {
+ dh.ra = dh.rd; // for good measure
+ }
+}
+
void setupLuaActions()
{
g_lua.writeFunction("newRuleAction", [](luadnsrule_t dnsrule, std::shared_ptr<DNSAction> action, boost::optional<luaruleparams_t> params) {
return std::shared_ptr<DNSAction>(new QPSPoolAction(limit, a));
});
- g_lua.writeFunction("SpoofAction", [](boost::variant<std::string,vector<pair<int, std::string>>> inp, boost::optional<std::string> b, boost::optional<spoofparams_t> vars ) {
+ g_lua.writeFunction("SpoofAction", [](boost::variant<std::string,vector<pair<int, std::string>>> inp, boost::optional<std::string> b, boost::optional<responseParams_t> vars ) {
vector<ComboAddress> addrs;
if(auto s = boost::get<std::string>(&inp))
addrs.push_back(ComboAddress(*s));
}
auto ret = std::shared_ptr<DNSAction>(new SpoofAction(addrs));
- boost::optional<bool> setAA = boost::none;
- boost::optional<bool> setAD = boost::none;
- boost::optional<bool> setRA = boost::none;
- parseSpoofConfig(vars, setAA, setAD, setRA);
auto sa = std::dynamic_pointer_cast<SpoofAction>(ret);
- if (setAA) {
- sa->setAA(*setAA);
- }
- if (setAD) {
- sa->setAD(*setAD);
- }
- if (setRA) {
- sa->setRA(*setRA);
- }
+ parseResponseConfig(vars, sa->d_responseConfig);
return ret;
});
- g_lua.writeFunction("SpoofCNAMEAction", [](const std::string& a, boost::optional<spoofparams_t> vars) {
+ g_lua.writeFunction("SpoofCNAMEAction", [](const std::string& a, boost::optional<responseParams_t> vars) {
auto ret = std::shared_ptr<DNSAction>(new SpoofAction(a));
- boost::optional<bool> setAA = boost::none;
- boost::optional<bool> setAD = boost::none;
- boost::optional<bool> setRA = boost::none;
- parseSpoofConfig(vars, setAA, setAD, setRA);
+ ResponseConfig responseConfig;
+ parseResponseConfig(vars, responseConfig);
auto sa = std::dynamic_pointer_cast<SpoofAction>(ret);
- if (setAA) {
- sa->setAA(*setAA);
- }
- if (setAD) {
- sa->setAD(*setAD);
- }
- if (setRA) {
- sa->setRA(*setRA);
- }
+ sa->d_responseConfig = responseConfig;
return ret;
-
});
g_lua.writeFunction("DropAction", []() {
return std::shared_ptr<DNSResponseAction>(new LogResponseAction(fname ? *fname : "", append ? *append : false, buffered ? *buffered : false, verboseOnly ? *verboseOnly : true, includeTimestamp ? *includeTimestamp : false));
});
- g_lua.writeFunction("RCodeAction", [](uint8_t rcode) {
- return std::shared_ptr<DNSAction>(new RCodeAction(rcode));
+ g_lua.writeFunction("RCodeAction", [](uint8_t rcode, boost::optional<responseParams_t> vars) {
+ auto ret = std::shared_ptr<DNSAction>(new RCodeAction(rcode));
+ auto rca = std::dynamic_pointer_cast<RCodeAction>(ret);
+ parseResponseConfig(vars, rca->d_responseConfig);
+ return ret;
});
- g_lua.writeFunction("ERCodeAction", [](uint8_t rcode) {
- return std::shared_ptr<DNSAction>(new ERCodeAction(rcode));
+ g_lua.writeFunction("ERCodeAction", [](uint8_t rcode, boost::optional<responseParams_t> vars) {
+ auto ret = std::shared_ptr<DNSAction>(new ERCodeAction(rcode));
+ auto erca = std::dynamic_pointer_cast<ERCodeAction>(ret);
+ parseResponseConfig(vars, erca->d_responseConfig);
+ return ret;
});
g_lua.writeFunction("SkipCacheAction", []() {
});
#ifdef HAVE_DNS_OVER_HTTPS
- g_lua.writeFunction("HTTPStatusAction", [](uint16_t status, std::string body, boost::optional<std::string> contentType) {
- return std::shared_ptr<DNSAction>(new HTTPStatusAction(status, body, contentType ? *contentType : ""));
+ g_lua.writeFunction("HTTPStatusAction", [](uint16_t status, std::string body, boost::optional<std::string> contentType, boost::optional<responseParams_t> vars) {
+ auto ret = std::shared_ptr<DNSAction>(new HTTPStatusAction(status, body, contentType ? *contentType : ""));
+ auto hsa = std::dynamic_pointer_cast<HTTPStatusAction>(ret);
+ parseResponseConfig(vars, hsa->d_responseConfig);
+ return ret;
});
#endif /* HAVE_DNS_OVER_HTTPS */
:param int v6: The IPv6 netmask length
-.. function:: ERCodeAction(rcode)
+.. function:: ERCodeAction(rcode [, options])
.. versionadded:: 1.4.0
+ .. versionchanged:: 1.5.0
+ Added the optional parameter ``options``.
+
Reply immediately by turning the query into a response with the specified EDNS extended ``rcode``.
``rcode`` can be specified as an integer or as one of the built-in :ref:`DNSRCode`.
:param int rcode: The extended RCODE to respond with.
+ :param table options: A table with key: value pairs with options.
-.. function:: HTTPStatusAction(status, body, contentType="")
+ Options:
+
+ * ``aa``: bool - Set the AA bit to this value (true means the bit is set, false means it's cleared). Default is to clear it.
+ * ``ad``: bool - Set the AD bit to this value (true means the bit is set, false means it's cleared). Default is to clear it.
+ * ``ra``: bool - Set the RA bit to this value (true means the bit is set, false means it's cleared). Default is to copy the value of the RD bit from the incoming query.
+
+.. function:: HTTPStatusAction(status, body, contentType="" [, options])
.. versionadded:: 1.4.0
+ .. versionchanged:: 1.5.0
+ Added the optional parameter ``options``.
+
Return an HTTP response with a status code of ''status''. For HTTP redirects, ''body'' should be the redirect URL.
:param int status: The HTTP status code to return.
:param string body: The body of the HTTP response, or a URL if the status code is a redirect (3xx).
:param string contentType: The HTTP Content-Type header to return for a 200 response, ignored otherwise. Default is ''application/dns-message''.
+ :param table options: A table with key: value pairs with options.
+
+ Options:
+
+ * ``aa``: bool - Set the AA bit to this value (true means the bit is set, false means it's cleared). Default is to clear it.
+ * ``ad``: bool - Set the AD bit to this value (true means the bit is set, false means it's cleared). Default is to clear it.
+ * ``ra``: bool - Set the RA bit to this value (true means the bit is set, false means it's cleared). Default is to copy the value of the RD bit from the incoming query.
.. function:: KeyValueStoreLookupAction(kvs, lookupKey, destinationTag)
:param int maxqps: The QPS limit for that pool
:param string poolname: The name of the pool
-.. function:: RCodeAction(rcode)
+.. function:: RCodeAction(rcode [, options])
+
+ .. versionchanged:: 1.5.0
+ Added the optional parameter ``options``.
Reply immediately by turning the query into a response with the specified ``rcode``.
``rcode`` can be specified as an integer or as one of the built-in :ref:`DNSRCode`.
:param int rcode: The RCODE to respond with.
+ :param table options: A table with key: value pairs with options.
+
+ Options:
+
+ * ``aa``: bool - Set the AA bit to this value (true means the bit is set, false means it's cleared). Default is to clear it.
+ * ``ad``: bool - Set the AD bit to this value (true means the bit is set, false means it's cleared). Default is to clear it.
+ * ``ra``: bool - Set the RA bit to this value (true means the bit is set, false means it's cleared). Default is to copy the value of the RD bit from the incoming query.
.. function:: RemoteLogAction(remoteLogger[, alterFunction [, options]])