/*
Technitium DNS Server
Copyright (C) 2024 Shreyas Zare (shreyas@technitium.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using TechnitiumLibrary.Net.Dns;
using TechnitiumLibrary.Net.Dns.ResourceRecords;
namespace DnsServerCore.ApplicationCommon
{
public enum DnsServerResponseType : byte
{
Authoritative = 1,
Recursive = 2,
Cached = 3,
Blocked = 4,
UpstreamBlocked = 5,
CacheBlocked = 6,
Dropped = 7
}
///
/// Allows a DNS App to log incoming DNS requests and their corresponding responses.
///
public interface IDnsQueryLogger
{
///
/// Allows a DNS App to log incoming DNS requests and responses. This method is called by the DNS Server after an incoming request is processed and a response is sent.
///
/// The time stamp of the log entry.
/// The incoming DNS request that was received.
/// The end point (IP address and port) of the client making the request.
/// The protocol using which the request was received.
/// The DNS response that was sent.
Task InsertLogAsync(DateTime timestamp, DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, DnsDatagram response);
///
/// Allows DNS Server HTTP API to query the logs recorded by the DNS App.
///
/// The page number to be displayed to the user.
/// Total entries per page.
/// Lists log entries in descending order.
/// Optional parameter to filter records by start date time.
/// Optional parameter to filter records by end date time.
/// Optional parameter to filter records by the client IP address.
/// Optional parameter to filter records by the DNS transport protocol.
/// Optional parameter to filter records by the type of response.
/// Optional parameter to filter records by the response code.
/// Optional parameter to filter records by the request QNAME.
/// Optional parameter to filter records by the request QTYPE.
/// Optional parameter to filter records by the request QCLASS.
/// The DnsLogPage
object that contains all the entries in the requested page number.
Task QueryLogsAsync(long pageNumber, int entriesPerPage, bool descendingOrder, DateTime? start, DateTime? end, IPAddress clientIpAddress, DnsTransportProtocol? protocol, DnsServerResponseType? responseType, DnsResponseCode? rcode, string qname, DnsResourceRecordType? qtype, DnsClass? qclass);
}
public class DnsLogPage
{
#region variables
readonly long _pageNumber;
readonly long _totalPages;
readonly long _totalEntries;
readonly IReadOnlyList _entries;
#endregion
#region constructor
///
/// Creates a new object initialized with all the log page parameters.
///
/// The actual page number of the selected data set.
/// The total pages for the selected data set.
/// The total number of entries in the selected data set.
/// The DNS log entries in this page.
public DnsLogPage(long pageNumber, long totalPages, long totalEntries, IReadOnlyList entries)
{
_pageNumber = pageNumber;
_totalPages = totalPages;
_totalEntries = totalEntries;
_entries = entries;
}
#endregion
#region properties
///
/// The actual page number of the selected data set.
///
public long PageNumber
{ get { return _pageNumber; } }
///
/// The total pages for the selected data set.
///
public long TotalPages
{ get { return _totalPages; } }
///
/// The total number of entries in the selected data set.
///
public long TotalEntries
{ get { return _totalEntries; } }
///
/// The DNS log entries in this page.
///
public IReadOnlyList Entries
{ get { return _entries; } }
#endregion
}
public class DnsLogEntry
{
#region variables
readonly long _rowNumber;
readonly DateTime _timestamp;
readonly IPAddress _clientIpAddress;
readonly DnsTransportProtocol _protocol;
readonly DnsServerResponseType _responseType;
readonly DnsResponseCode _rcode;
readonly DnsQuestionRecord _question;
readonly string _answer;
#endregion
#region constructor
///
/// Creates a new object initialized with all the log entry parameters.
///
/// The row number of the entry in the selected data set.
/// The time stamp of the log entry.
/// The client IP address of the request.
/// The DNS transport protocol of the request.
/// The type of response sent by the DNS server.
/// The response code sent by the DNS server.
/// The question section in the request.
/// The answer in text format sent by the DNS server.
public DnsLogEntry(long rowNumber, DateTime timestamp, IPAddress clientIpAddress, DnsTransportProtocol protocol, DnsServerResponseType responseType, DnsResponseCode rcode, DnsQuestionRecord question, string answer)
{
_rowNumber = rowNumber;
_timestamp = timestamp;
_clientIpAddress = clientIpAddress;
_protocol = protocol;
_responseType = responseType;
_rcode = rcode;
_question = question;
_answer = answer;
switch (_timestamp.Kind)
{
case DateTimeKind.Local:
_timestamp = _timestamp.ToUniversalTime();
break;
case DateTimeKind.Unspecified:
_timestamp = DateTime.SpecifyKind(_timestamp, DateTimeKind.Utc);
break;
}
}
#endregion
#region properties
///
/// The row number of the entry in the selected data set.
///
public long RowNumber
{ get { return _rowNumber; } }
///
/// The time stamp of the log entry.
///
public DateTime Timestamp
{ get { return _timestamp; } }
///
/// The client IP address of the request.
///
public IPAddress ClientIpAddress
{ get { return _clientIpAddress; } }
///
/// The DNS transport protocol of the request.
///
public DnsTransportProtocol Protocol
{ get { return _protocol; } }
///
/// The type of response sent by the DNS server.
///
public DnsServerResponseType ResponseType
{ get { return _responseType; } }
///
/// The response code sent by the DNS server.
///
public DnsResponseCode RCODE
{ get { return _rcode; } }
///
/// The question section in the request.
///
public DnsQuestionRecord Question
{ get { return _question; } }
///
/// The answer in text format sent by the DNS server.
///
public string Answer
{ get { return _answer; } }
#endregion
}
}