nDPI的DNS协议解析
1. 说明
把nDpi的DNS协议解析部分拿出来看看,写了一些注释。使用的是nDpi的1.6版本,该版本下的文件结构比较简单,协议解析的代码都在 src/lib/protocols目录下。dns的解析代码自然就是dns.c了。nDpi的协议解析代码基本有着相同的结构,协议解析的入口函数一般定义为 ndpi_search_###。比如DNS的入口函数就是ndpi_search_dns()。
2. 工具函数
这个文件下还有几个简单的函数:
// 一个递归的函数来计算dns中域名字段占据报文的长度
static u_int getNameLength
//用来计算ip地址的,
static char* ndpi_intoa_v4
// 用报文中得到一个16字节的整数
static u_int16_t get16
3. 源代码注释
// dns 的入口函数
void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct *packet = &flow->packet; // 定义包接口
u_int16_t dport = 0, sport = 0;
#define NDPI_MAX_DNS_REQUESTS 16
NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "search DNS.\n"); // 打日志
// 根据使用的是tcp还是udp,获取端口号
if (packet->udp != NULL) {
sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "calculated dport over UDP.\n");
} else if(packet->tcp != NULL) {
sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "calculated dport over tcp.\n");
}
// 如果端口包含53 可以确定为dns协议。否则退出整个函数。并且有数据内容。这个if一直到函数的结尾了
if(((dport == 53) || (sport == 53) || (dport == 5355))
&& (packet->payload_packet_len > sizeof(struct dns_packet_header))) {
int i = packet->tcp ? 2 : 0; // 一般dns协议使用的是udp协议。DNS服务器之间才会使用tcp。如果是tcp协议的话,需要偏移两个字节,??为什么
struct dns_packet_header header, *dns = (struct dns_packet_header*)&packet->payload[i];
u_int8_t is_query, ret_code, is_dns = 0;
u_int32_t a_record[NDPI_MAX_DNS_REQUESTS] = { 0 }, query_offset, num_a_records = 0;
// 获取dns协议的头部,将网络字节序转换为本地字节序
header.