C语言中的DNS客户端

3

我目前正在进行一个学校项目,要求我实现一个DNS客户端,但不能使用任何库函数。

我已经可以发送DNS请求并接收响应。但在解析响应时卡住了。我接收到的响应是char*数组,我想将其转换为一些有意义的结构,以便从中解析答案。我阅读了RFC并了解了数据包结构,但在C语言中实现它给我带来了问题。

请问有人可以给我提供任何示例,用C语言或其他任何语言来解释如何完成这个任务。或者任何参考书籍也可以。

附加细节:

所以,我正在使用以下结构:

struct result{
  int type;
  struct res_ip_cname ip_cname;
  struct res_error error;
  struct res_mx_ns mx_ns;
};

struct res_ip_cname{
  char* lst;
  int sec;
  char* auth_flag;
};

struct res_error{
  char * info;
};

struct res_mx_ns{
  char * name;
  unsigned short pref;
  int sec;
  char* auth_flag;
};

我有一个char* buffer[],我将从服务器接收到的响应存储在其中。我需要从这个缓冲区中提取信息并填充结果结构体。
谢谢, Chander
4个回答

6
您的结构看起来不像我从RFC中认识的任何东西(是的,我写过很多DNS数据包解码软件)。
特别是看看 RFC 1035 - 您需要的大多数结构可以直接从其中显示的字段布局进行映射。
例如,您需要一个标题(请参见s4.1.1):
struct dns_header {
     uint16_t     query_id;
     uint16_t     flags;
     uint16_t     qdcount;
     uint16_t     ancount;
     uint16_t     nscount;
     uint16_t     arcount;
};

不要忘记使用ntohs()将这些字段的线格式转换为您计算机的本地字节顺序。网络字节顺序是大端,而大多数现代计算机是小端。
您需要一个“问题”结构(请参见s4.1.2),还需要一个通用的“资源记录”结构(请参见s4.1.3)。
但请注意,这两个的线格式都以可变长度的“标签”开头,其中也可以包括压缩指针(请参见s4.1.4)。这意味着在这些情况下,您无法将整个线块简单地映射到C结构上。
希望这有所帮助...

0

如果我是你,我会使用wireshark(结合RFC)来检查数据包结构。Wireshark可以捕获和显示通过计算机流动的网络数据包。它让你看到你将要接收到的原始数据和解码后的数据包结构。

例如,在下面的截图中,你可以看到chat.meta.stackoverflow.com的IP地址以三种不同的方式呈现在DNS响应数据包中。首先,在屏幕的中间窗格中,你可以看到一个人类可读的版本。其次,左下窗格中的高亮文本显示了原始DNS数据包作为一系列十六进制字节。第三,在左下窗格中的高亮文本中,你可以看到数据包呈ASCII文本形式呈现(在这种情况下,大部分但不完全是胡言乱语)。 a wireshark trace of a DNS response packet


0

请求格式响应格式非常相似 - 都包含可变长度的字段,我猜这就是你卡住的地方 - 但如果你已经成功地形成了一个请求,那么解析响应应该不会太困难。如果你能提供更多细节,比如你卡在哪里,我们可以更好地帮助你。


-1

我的建议是不要把它弄得太复杂。从头部提取QDCOUNTANCOUNT,然后跳过头部,跳过QDCOUNT个问题,并开始解析答案。跳过标签很容易(只需查找第一个字节为0或高位设置的字节),但解码则需要更多的工作(您需要跟随和验证“指针”,并确保不会陷入循环)。如果您只查找地址(而不是PTR记录),则根本不需要解码标签。


即使是“A”级答案,使用标签也很常见 - 通常答案中的“name”字段是指向问题的标签。 - caf
但是,除非您想要(1)检查答案是否实际上是您查询的答案,或者(2)在您查找的名称导致CNAME记录和相应的AAAAA记录时获取规范名称,否则没有理由在查找地址时解析标签。而跳过它们比解析它们容易得多。 :-) - R.. GitHub STOP HELPING ICE
这是错误的建议 - 实际上可能会遇到包含高位设置字符的标签(即使很少见)。 - Alnitak
避免循环非常简单 - 只需丢弃包含前向指针的任何数据包即可。压缩指针只能指向相同标签序列的_prior_实例,如果只能向后移动,则无法创建循环。 - Alnitak
无论如何,实际上半解析标签更有效率,因为如果标签计数字段不是压缩指针,你可以立即跳过那么多字节,而不是在每个后续字节上执行不正确的位测试。如果它是合法的压缩指针,你只需跳过下一个字节,就知道已经到达该标签序列的末尾了。 - Alnitak
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接