]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/dnsdist.cc
dnsdist: Allow wrapping the FFI interface for the existing DNSQuestion object
[thirdparty/pdns.git] / pdns / dnsdist.cc
index 96af451cf7f52905ac9b89ef937312c923e6f37f..75d7c56ea299d30c8a31bd31fb61128377ee9d9c 100644 (file)
@@ -37,6 +37,7 @@
 #include <editline/readline.h>
 #endif
 
+#include "dnsdist-systemd.hh"
 #ifdef HAVE_SYSTEMD
 #include <systemd/sd-daemon.h>
 #endif
@@ -81,7 +82,6 @@ using std::thread;
 bool g_verbose;
 
 struct DNSDistStats g_stats;
-MetricDefinitionStorage g_metricDefinitions;
 
 uint16_t g_maxOutstanding{std::numeric_limits<uint16_t>::max()};
 uint32_t g_staleCacheEntriesTTL{0};
@@ -193,6 +193,30 @@ struct DelayedPacket
 
 DelayPipe<DelayedPacket>* g_delay = nullptr;
 
+std::string DNSQuestion::getTrailingData() const
+{
+  const char* message = reinterpret_cast<const char*>(this->dh);
+  const uint16_t messageLen = getDNSPacketLength(message, this->len);
+  return std::string(message + messageLen, this->len - messageLen);
+}
+
+bool DNSQuestion::setTrailingData(const std::string& tail)
+{
+  char* message = reinterpret_cast<char*>(this->dh);
+  const uint16_t messageLen = getDNSPacketLength(message, this->len);
+  const uint16_t tailLen = tail.size();
+  if (tailLen > (this->size - messageLen)) {
+    return false;
+  }
+
+  /* Update length and copy data from the Lua string. */
+  this->len = messageLen + tailLen;
+  if(tailLen > 0) {
+    tail.copy(message + messageLen, tailLen);
+  }
+  return true;
+}
+
 void doLatencyStats(double udiff)
 {
   if(udiff < 1000) ++g_stats.latency0_1;
@@ -1031,34 +1055,41 @@ NumberedServerVector getDownstreamCandidates(const pools_t& pools, const std::st
   return pool->getServers();
 }
 
-static void spoofResponseFromString(DNSQuestion& dq, const string& spoofContent)
+static void spoofResponseFromString(DNSQuestion& dq, const string& spoofContent, bool raw)
 {
   string result;
 
-  std::vector<std::string> addrs;
-  stringtok(addrs, spoofContent, " ,");
+  if (raw) {
+    SpoofAction sa(spoofContent);
+    sa(&dq, &result);
+  }
+  else {
+    std::vector<std::string> addrs;
+    stringtok(addrs, spoofContent, " ,");
 
-  if (addrs.size() == 1) {
-    try {
-      ComboAddress spoofAddr(spoofContent);
-      SpoofAction sa({spoofAddr});
-      sa(&dq, &result);
-    }
-    catch(const PDNSException &e) {
-      SpoofAction sa(spoofContent); // CNAME then
-      sa(&dq, &result);
-    }
-  } else {
-    std::vector<ComboAddress> cas;
-    for (const auto& addr : addrs) {
+    if (addrs.size() == 1) {
       try {
-        cas.push_back(ComboAddress(addr));
+        ComboAddress spoofAddr(spoofContent);
+        SpoofAction sa({spoofAddr});
+        sa(&dq, &result);
       }
-      catch (...) {
+      catch(const PDNSException &e) {
+        DNSName cname(spoofContent);
+        SpoofAction sa(cname); // CNAME then
+        sa(&dq, &result);
       }
+    } else {
+      std::vector<ComboAddress> cas;
+      for (const auto& addr : addrs) {
+        try {
+          cas.push_back(ComboAddress(addr));
+        }
+        catch (...) {
+        }
+      }
+      SpoofAction sa(cas);
+      sa(&dq, &result);
     }
-    SpoofAction sa(cas);
-    sa(&dq, &result);
   }
 }
 
@@ -1092,7 +1123,11 @@ bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::s
     return true;
     break;
   case DNSAction::Action::Spoof:
-    spoofResponseFromString(dq, ruleresult);
+    spoofResponseFromString(dq, ruleresult, false);
+    return true;
+    break;
+  case DNSAction::Action::SpoofRaw:
+    spoofResponseFromString(dq, ruleresult, true);
     return true;
     break;
   case DNSAction::Action::Truncate:
@@ -1525,7 +1560,7 @@ ProcessQueryResult processQuery(DNSQuestion& dq, ClientState& cs, LocalHolders&
         }
       }
 
-      if (!handleEDNSClientSubnet(dq, &(dq.ednsAdded), &(dq.ecsAdded), g_preserveTrailingData)) {
+      if (!handleEDNSClientSubnet(dq, dq.ednsAdded, dq.ecsAdded, g_preserveTrailingData)) {
         vinfolog("Dropping query from %s because we couldn't insert the ECS value", dq.remote->toStringWithPort());
         return ProcessQueryResult::Drop;
       }
@@ -2579,8 +2614,8 @@ try
   }
 #endif
 
-  uid_t newgid=0;
-  gid_t newuid=0;
+  uid_t newgid=getegid();
+  gid_t newuid=geteuid();
 
   if(!g_cmdLine.gid.empty())
     newgid = strToGID(g_cmdLine.gid.c_str());
@@ -2588,8 +2623,22 @@ try
   if(!g_cmdLine.uid.empty())
     newuid = strToUID(g_cmdLine.uid.c_str());
 
-  dropGroupPrivs(newgid);
-  dropUserPrivs(newuid);
+  if (getegid() != newgid) {
+    if (running_in_service_mgr()) {
+      errlog("--gid/-g set on command-line, but dnsdist was started as a systemd service. Use the 'Group' setting in the systemd unit file to set the group to run as");
+      _exit(EXIT_FAILURE);
+    }
+    dropGroupPrivs(newgid);
+  }
+
+  if (geteuid() != newuid) {
+    if (running_in_service_mgr()) {
+      errlog("--uid/-u set on command-line, but dnsdist was started as a systemd service. Use the 'User' setting in the systemd unit file to set the user to run as");
+      _exit(EXIT_FAILURE);
+    }
+    dropUserPrivs(newuid);
+  }
+
   try {
     /* we might still have capabilities remaining,
        for example if we have been started as root