def printResponse(self, message):
if message.HasField('response'):
response = message.response
+
+ if response.HasField('queryTimeSec'):
+ datestr = datetime.datetime.fromtimestamp(response.queryTimeSec).strftime('%Y-%m-%d %H:%M:%S')
+ if response.HasField('queryTimeUsec'):
+ datestr = datestr + '.' + str(response.queryTimeUsec)
+ print("- Query time: %s" % (datestr))
+
policystr = ''
if response.HasField('appliedPolicy') and response.appliedPolicy:
policystr = ', Applied policy: ' + response.appliedPolicy
}
};
+DNSDistProtoBufMessage::DNSDistProtoBufMessage(const DNSResponse& dr): DNSProtoBufMessage(Response, dr.uniqueId, dr.remote, dr.local, *dr.qname, dr.qtype, dr.qclass, dr.dh->id, dr.tcp, dr.len)
+{
+ setQueryTime(dr.queryTime->tv_sec, dr.queryTime->tv_nsec / 1000);
+ setResponseCode(dr.dh->rcode);
+ addRRsFromPacket((const char*) dr.dh, dr.len);
+};
+
#endif /* HAVE_PROTOBUF */
{
public:
DNSDistProtoBufMessage(DNSProtoBufMessageType type, const DNSQuestion& dq);
+ DNSDistProtoBufMessage(const DNSResponse& dr);
};
string poolname;
int delayMsec=0;
struct timespec now;
- gettime(&now);
+ gettime(&now, true);
if (!processQuery(localDynBlockNMG, localDynBlockSMT, localRulactions, blockFilter, dq, poolname, &delayMsec, now)) {
goto drop;
}
dh = (struct dnsheader*) response;
- DNSQuestion dr(&qname, qtype, qclass, &ci.cs->local, &ci.remote, dh, responseSize, responseLen, true);
+ DNSResponse dr(&qname, qtype, qclass, &ci.cs->local, &ci.remote, dh, responseSize, responseLen, true, &now);
#ifdef HAVE_PROTOBUF
dr.uniqueId = dq.uniqueId;
#endif
dh->id = ids->origID;
uint16_t addRoom = 0;
- DNSQuestion dr(&ids->qname, ids->qtype, ids->qclass, &ids->origDest, &ids->origRemote, dh, sizeof(packet), responseLen, false);
+ DNSResponse dr(&ids->qname, ids->qtype, ids->qclass, &ids->origDest, &ids->origRemote, dh, sizeof(packet), responseLen, false, &ids->sentTime.d_start);
#ifdef HAVE_PROTOBUF
dr.uniqueId = ids->uniqueId;
#endif
return true;
}
-bool processResponse(LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > >& localRespRulactions, DNSQuestion& dr)
+bool processResponse(LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > >& localRespRulactions, DNSResponse& dr)
{
std::string ruleresult;
for(const auto& lr : *localRespRulactions) {
struct StopWatch
{
+ StopWatch(bool realTime=false): d_needRealTime(realTime)
+ {
+ }
struct timespec d_start{0,0};
+ bool d_needRealTime{false};
+
void start() {
- if(gettime(&d_start) < 0)
+ if(gettime(&d_start, d_needRealTime) < 0)
unixDie("Getting timestamp");
}
double udiff() const {
struct timespec now;
- if(gettime(&now) < 0)
+ if(gettime(&now, d_needRealTime) < 0)
unixDie("Getting timestamp");
return 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
double udiffAndSet() {
struct timespec now;
- if(gettime(&now) < 0)
+ if(gettime(&now, d_needRealTime) < 0)
unixDie("Getting timestamp");
auto ret= 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
struct IDState
{
- IDState() : origFD(-1), delayMsec(0) { origDest.sin4.sin_family = 0;}
+ IDState() : origFD(-1), sentTime(true), delayMsec(0) { origDest.sin4.sin_family = 0;}
IDState(const IDState& orig)
{
origFD = orig.origFD;
bool skipCache{false};
};
+struct DNSResponse : DNSQuestion
+{
+ DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t queryLen, bool isTcp, const struct timespec* queryTime_): DNSQuestion(name, type, class_, lc, rem, header, bufferSize, queryLen, isTcp), queryTime(queryTime_) { }
+
+ const struct timespec* queryTime;
+};
+
typedef std::function<bool(const DNSQuestion*)> blockfilter_t;
template <class T> using NumberedVector = std::vector<std::pair<unsigned int, T> >;
{
public:
enum class Action { None };
- virtual Action operator()(DNSQuestion*, string* ruleresult) const =0;
+ virtual Action operator()(DNSResponse*, string* ruleresult) const =0;
virtual string toString() const = 0;
};
bool responseContentMatches(const char* response, const uint16_t responseLen, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote);
bool processQuery(LocalStateHolder<NetmaskTree<DynBlock> >& localDynBlockNMG,
LocalStateHolder<SuffixMatchTree<DynBlock> >& localDynBlockSMT, LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction> > > >& localRulactions, blockfilter_t blockFilter, DNSQuestion& dq, string& poolname, int* delayMsec, const struct timespec& now);
-bool processResponse(LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > >& localRespRulactions, DNSQuestion& dq);
+bool processResponse(LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > >& localRespRulactions, DNSResponse& dr);
bool fixUpResponse(char** response, uint16_t* responseLen, size_t* responseSize, const DNSName& qname, uint16_t origFlags, bool ednsAdded, bool ecsAdded, std::vector<uint8_t>& rewrittenResponse, uint16_t addRoom);
void restoreFlags(struct dnsheader* dh, uint16_t origFlags);
repeated DNSRR rrs = 2;
optional string appliedPolicy = 3;
repeated string tags = 4;
+ optional uint32 queryTimeSec = 5;
+ optional uint32 queryTimeUsec = 6;
}
optional DNSResponse response = 13;
if(argc==4)
ind=atoi(argv[3]);
- std::map<uint16_t,boost::uuids::uuid> ids;
+ std::map<uint16_t,std::pair<boost::uuids::uuid,struct timeval> > ids;
boost::uuids::random_generator uuidGenerator;
try {
while (pr.getUDPPacket()) {
}
boost::uuids::uuid uniqueId;
+ struct timeval queryTime = { 0, 0 };
+ bool hasQueryTime = false;
if (!dh->qr) {
+ queryTime.tv_sec = pr.d_pheader.ts.tv_sec;
+ queryTime.tv_usec = pr.d_pheader.ts.tv_usec;
uniqueId = uuidGenerator();
- ids[dh->id] = uniqueId;
+ ids[dh->id] = std::make_pair(uniqueId, queryTime);
}
else {
const auto& it = ids.find(dh->id);
if (it != ids.end()) {
- uniqueId = it->second;
+ uniqueId = it->second.first;
+ queryTime = it->second.second;
+ hasQueryTime = true;
}
else {
uniqueId = uuidGenerator();
if (dh->qr) {
message.setResponseCode(dh->rcode);
+ if (hasQueryTime) {
+ message.setQueryTime(queryTime.tv_sec, queryTime.tv_usec);
+ }
+
try {
message.addRRsFromPacket((const char*) dh, pr.d_len);
}
RemoteLogResponseAction(std::shared_ptr<RemoteLogger> logger): d_logger(logger)
{
}
- DNSResponseAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
+ DNSResponseAction::Action operator()(DNSResponse* dr, string* ruleresult) const override
{
#ifdef HAVE_PROTOBUF
- DNSDistProtoBufMessage message(DNSDistProtoBufMessage::Response, *dq);
+ DNSDistProtoBufMessage message(*dr);
std::string data;
message.serialize(data);
d_logger->queueData(data);
pbMessage.setResponseCode(pw.getHeader()->rcode);
pbMessage.setAppliedPolicy(appliedPolicy);
pbMessage.setPolicyTags(dc->d_policyTags);
+ pbMessage.setQueryTime(dc->d_now.tv_sec, dc->d_now.tv_usec);
protobufLogResponse(luaconfsLocal->protobufServer, pbMessage);
}
#endif
const ComboAddress& requestor = requestorNM.getMaskedNetwork();
pbMessage.update(uniqueId, &requestor, &destaddr, false, dh->id);
pbMessage.setEDNSSubnet(ednssubnet);
+ pbMessage.setQueryTime(g_now.tv_sec, g_now.tv_usec);
protobufLogResponse(luaconfsLocal->protobufServer, pbMessage);
}
#endif /* HAVE_PROTOBUF */
#endif /* HAVE_PROTOBUF */
}
+void DNSProtoBufMessage::setQueryTime(time_t sec, uint32_t usec)
+{
+#ifdef HAVE_PROTOBUF
+ PBDNSMessage_DNSResponse* response = d_message.mutable_response();
+ if (response) {
+ response->set_querytimesec(sec);
+ response->set_querytimeusec(usec);
+ }
+#endif /* HAVE_PROTOBUF */
+}
+
void DNSProtoBufMessage::setEDNSSubnet(const Netmask& subnet)
{
#ifdef HAVE_PROTOBUF
void setEDNSSubnet(const Netmask& subnet);
void setBytes(size_t bytes);
void setTime(time_t sec, uint32_t usec);
+ void setQueryTime(time_t sec, uint32_t usec);
void setResponseCode(uint8_t rcode);
void addRRsFromPacket(const char* packet, const size_t len);
void serialize(std::string& data) const;