]> granicus.if.org Git - pdns/commitdiff
implement mac address stuffing in dnsdist FOR QUERIES WITHOUT EDNS ALREADY.
authorbert hubert <bert.hubert@powerdns.com>
Wed, 27 Jan 2016 11:34:34 +0000 (12:34 +0100)
committerbert hubert <bert.hubert@powerdns.com>
Wed, 27 Jan 2016 11:34:34 +0000 (12:34 +0100)
pdns/dnsdist-lua.cc
pdns/dnsrulactions.hh
pdns/misc.cc
pdns/misc.hh

index d05baf19d5ae6b9cd37e8d898d44240356f10a51..62562ac290b8ac32ef3b2a9544ae2c0d6e002c94 100644 (file)
@@ -536,6 +536,11 @@ vector<std::function<void(void)>> setupLua(bool client, const std::string& confi
       return std::shared_ptr<DNSAction>(new NoRecurseAction);
     });
 
+  g_lua.writeFunction("MacAddrAction", [](int code) {
+      return std::shared_ptr<DNSAction>(new MacAddrAction(code));
+    });
+
+
   g_lua.writeFunction("PoolAction", [](const string& a) {
       return std::shared_ptr<DNSAction>(new PoolAction(a));
     });
index 5af45777ff316463a0b18d5a06afcb9d0c0d2609..b047d7beb563347224fd92d1229b3754415331d0 100644 (file)
@@ -511,6 +511,51 @@ private:
   DNSName d_cname;
 };
 
+class MacAddrAction : public DNSAction
+{
+public:
+  MacAddrAction(uint16_t code) : d_code(code)
+  {}
+  DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
+  {
+    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 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();
+    }
+    return Action::None;
+  }  
+  string toString() const override
+  {
+    return "add EDNS MAC (code="+std::to_string(d_code)+")";
+  }
+private:
+  uint16_t d_code{3};
+};
 
 class NoRecurseAction : public DNSAction
 {
index b60eb6dc2d4a8cbe10765b2aaf3b988f490858c6..e4eb2d58a9355893c9caeadc8b5ff573e09dc606 100644 (file)
@@ -1082,6 +1082,32 @@ bool setCloseOnExec(int sock)
   return true;
 }
 
+string getMACAddress(const ComboAddress& ca)
+{
+  string ret;
+#ifdef __linux__
+  ifstream ifs("/proc/net/arp");
+  if(!ifs)
+    return ret;
+  string line;
+  string match=ca.toString()+' ';
+  while(getline(ifs, line)) {
+    if(boost::starts_with(line, match)) {
+      vector<string> parts;
+      stringtok(parts, line, " \n\t\r");
+      if(parts.size() < 4)
+        return ret;
+      unsigned int tmp[6];
+      sscanf(parts[3].c_str(), "%02x:%02x:%02x:%02x:%02x:%02x", tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5);
+      for(int i = 0 ; i< 6 ; ++i)
+        ret.append(1, (char)tmp[i]);
+      return ret;
+    }
+  }
+#endif
+  return ret;
+}
+
 uint64_t udpErrorStats(const std::string& str)
 {
 #ifdef __linux__
index 51cae92f9f416cd25bc8447e9cdb11af5069947c..731c3df8cd1da473da9fd58aacaa3d5dec63c908 100644 (file)
@@ -609,7 +609,7 @@ uint64_t getRealMemoryUsage(const std::string&);
 uint64_t getOpenFileDescriptors(const std::string&);
 uint64_t getCPUTimeUser(const std::string&);
 uint64_t getCPUTimeSystem(const std::string&);
-
+std::string getMACAddress(const ComboAddress& ca);
 template<typename T, typename... Args>
 std::unique_ptr<T> make_unique(Args&&... args)
 {