【UEFI基础】EDK网络框架(DNS4)

DNS4

DNS4协议说明

IP地址是一串数据,不便记忆。一般用户在使用TCP/IP协议进行通信时也不使用IP地址,而是使用英文和点号组成的字符串,两者的转换通过DNS(Domain Name System)来完成。

DNS也有v4和v6版本,这里只介绍v4版本。其报文格式如下:

在这里插入图片描述

各个参数的说明如下:

字段长度(bit)描述
Header96头部字段,是必须存在的,它定义了报文是请求还是应答,也定义了其他段是否需要存在,以及是标准查询还是其他。
Question变长大多数查询中,Question段包含着问题(question),比如,指定问什么。
这个段包含QDCOUNT(头部字段中的QDCOUNT字段,通常值是1)个问题。
Anser变长分别指应答,授权,附加字段。
都共用相同的格式:多个资源记录,资源记录的个数由报文头段中对应的几个数值确定。
Authority变长
Additianal变长

其中的头部有12个字节,内容如下:

在这里插入图片描述

各个参数的说明如下:

字段长度(bit)描述
ID16标识字段,客户通过标识字段来确定DNS响应是否与查询请求匹配。
QR1操作类型:
0:查询报文
1:响应报文
OPCODE4查询类型:
0:标准查询
1:反向查询
2:服务器状态查询
3~15:保留未用反向查询是客户端请求服务器根据回答生成导致此回答的问题,这个查询类型的使用并不多。
AA1若置位,则表示该域名解析服务器是授权回答该域的。
TC1若置位,则表示报文被截断。使用UDP传输时,应答的总长度超过512字节时,只返回报文的前512个字节内容。
RD1客户端希望域名解析服务器采取的解析方式:
0:表示希望域名解析服务器采取迭代解析
1:表示希望域名解析服务器采取递归解析
RA1域名解析服务器采取的解析方式:
0:表示域名解析服务器采取迭代解析
1:表示域名解析服务器采取递归解析
Z3全部置0,保留未用。
RCODE4响应类型:
0:无差错
1:查询格式错
2:服务器失效
3:域名不存在
4:查询没有被执行
5:查询被拒绝
6-15: 保留未用
QDCOUNT16无符号16位整数表示报文请求段中的问题记录数。
ANCOUNT16无符号16位整数表示报文回答段中的回答记录数。
NSCOUNT16无符号16位整数表示报文授权段中的授权记录数。
ARCOUNT16无符号16位整数表示报文附加段中的附加记录数。

对应代码中的结构体:

union _DNS_FLAGS {struct {UINT16    RCode  : 4;UINT16    Zero   : 3;UINT16    RA     : 1;UINT16    RD     : 1;UINT16    TC     : 1;UINT16    AA     : 1;UINT16    OpCode : 4;UINT16    QR     : 1;} Bits;UINT16    Uint16;
};typedef struct {UINT16       Identification;DNS_FLAGS    Flags;UINT16       QuestionsNum;UINT16       AnswersNum;UINT16       AuthorityNum;UINT16       AditionalNum;
} DNS_HEADER;

后面变长部分的内容,后面如何使用到再介绍。

DNS4代码综述

UDP4也是一个通用的网络协议,其实现在NetworkPkg\DnsDxe\DnsDxe.inf,这里首先需要看下它的入口:

EFI_STATUS
EFIAPI
DnsDriverEntryPoint (IN EFI_HANDLE        ImageHandle,IN EFI_SYSTEM_TABLE  *SystemTable)
{//// Install the Dns4 Driver Binding Protocol.//Status = EfiLibInstallDriverBindingComponentName2 (ImageHandle,SystemTable,&gDns4DriverBinding,ImageHandle,&gDnsComponentName,&gDnsComponentName2);//// Install the Dns6 Driver Binding Protocol.//Status = EfiLibInstallDriverBindingComponentName2 (ImageHandle,SystemTable,&gDns6DriverBinding,NULL,&gDnsComponentName,&gDnsComponentName2);//// Create the driver data structures.//mDriverData = AllocateZeroPool (sizeof (DNS_DRIVER_DATA));//// Create the timer event to update DNS cache list.//Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL | EVT_TIMER,TPL_CALLBACK,DnsOnTimerUpdate,NULL,&mDriverData->Timer);Status = gBS->SetTimer (mDriverData->Timer, TimerPeriodic, TICKS_PER_SECOND);InitializeListHead (&mDriverData->Dns4CacheList);InitializeListHead (&mDriverData->Dns4ServerList);InitializeListHead (&mDriverData->Dns6CacheList);InitializeListHead (&mDriverData->Dns6ServerList);
}

从这里可以看到会安装v4和v6版本的EFI_DRIVER_BINDING_PROTOCOL接口,不过这里只关注v4版本的:

EFI_DRIVER_BINDING_PROTOCOL  gDns4DriverBinding = {Dns4DriverBindingSupported,Dns4DriverBindingStart,Dns4DriverBindingStop,DNS_VERSION,NULL,NULL
};

除此之外,这里还为DNS_DRIVER_DATA分配了内存,并初始化了部分内容,最重要的是有一个定时器,是用来更新DNS缓存列表的,其结构体如下:

struct _DNS_DRIVER_DATA {EFI_EVENT     Timer;                 /// Ticking timer for DNS cache update.LIST_ENTRY    Dns4CacheList;LIST_ENTRY    Dns4ServerList;LIST_ENTRY    Dns6CacheList;LIST_ENTRY    Dns6ServerList;
};

DNS4在UEFI网络协议栈中的关系图:

支持
提供
支持
支持
提供
支持
提供
提供
提供
支持
提供
提供
支持
支持
提供
提供
提供
支持
提供
提供
gEfiPciIoProtocolGuid
UNDI
gEfiNetworkInterfaceIdentifierProtocolGuid_31
gEfiDevicePathProtocolGuid
SNP
gEfiSimpleNetworkProtocolGuid
MNP
gEfiVlanConfigProtocolGuid
gEfiManagedNetworkServiceBindingProtocolGuid
gEfiManagedNetworkProtocolGuid
ARP
gEfiArpServiceBindingProtocolGuid
gEfiArpProtocolGuid
IP4
gEfiIp4ServiceBindingProtocolGuid
gEfiIp4Config2ProtocolGuid
gEfiIp4ProtocolGuid
DHCP4
gEfiDns4ServiceBindingProtocolGuid
gEfiDns4ProtocolGuid

Dns4DriverBindingSupported

DNS4依赖于UDP4:

EFI_STATUS
EFIAPI
Dns4DriverBindingSupported (IN EFI_DRIVER_BINDING_PROTOCOL  *This,IN EFI_HANDLE                   ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL)
{//// Test for the Udp4ServiceBinding Protocol.//Status = gBS->OpenProtocol (ControllerHandle,&gEfiUdp4ServiceBindingProtocolGuid,NULL,This->DriverBindingHandle,ControllerHandle,EFI_OPEN_PROTOCOL_TEST_PROTOCOL
}

Dns4DriverBindingStart

Start函数的流程大致如下:

  1. 初始化DNS_SERVICE
  2. 安装gEfiDns4ServiceBindingProtocolGuid

同其它驱动一样,重点也是结构体,这里就是DNS_SERVICE

DNS_SERVICE

DNS_SERVICE在Start函数中创建:

EFI_STATUS
EFIAPI
Dns4DriverBindingStart (IN EFI_DRIVER_BINDING_PROTOCOL  *This,IN EFI_HANDLE                   ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL)
{Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4, &DnsSb);Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND);

其结构体定义如下:

struct _DNS_SERVICE {UINT32                          Signature;EFI_SERVICE_BINDING_PROTOCOL    ServiceBinding;UINT16                          Dns4ChildrenNum;LIST_ENTRY                      Dns4ChildrenList;UINT16                          Dns6ChildrenNum;LIST_ENTRY                      Dns6ChildrenList;EFI_HANDLE                      ControllerHandle;EFI_HANDLE                      ImageHandle;EFI_EVENT                       TimerToGetMap;EFI_EVENT                       Timer; /// Ticking timer for packet retransmission.UINT8                           IpVersion;UDP_IO                          *ConnectUdp;
};

其中比较重要的成员有:

  • ServiceBinding:对应mDns4ServiceBinding
EFI_SERVICE_BINDING_PROTOCOL  mDns4ServiceBinding = {Dns4ServiceBindingCreateChild,Dns4ServiceBindingDestroyChild
};
  • Dns4ChildrenNumDns4ChildrenList:对应DNS4子项,在Dns4ServiceBindingCreateChild()中创建。
  • TimerToGetMap:其说明如下:
  //// Create the timer used to time out the procedure which is used to// get the default IP address.//Status = gBS->CreateEvent (EVT_TIMER,TPL_CALLBACK,NULL,NULL,&DnsSb->TimerToGetMap);
  • Timer:其说明如下:
  //// Create the timer to retransmit packets.//Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL | EVT_TIMER,TPL_CALLBACK,DnsOnTimerRetransmit,DnsSb,&DnsSb->Timer);
  • IpVersion:对应DNS4来说就是IP_VERSION_4
  • ConnectUdp:对应结构体UDP_IO
struct _UDP_IO {UINT32                     Signature;LIST_ENTRY                 Link;INTN                       RefCnt;UINT8                      UdpVersion;//// Handle used to create/destroy UDP child//EFI_HANDLE                 Controller;EFI_HANDLE                 Image;EFI_HANDLE                 UdpHandle;EFI_SIMPLE_NETWORK_MODE    SnpMode;LIST_ENTRY                 SentDatagram;  ///< A list of UDP_TX_TOKEN.UDP_RX_TOKEN               *RecvRequest;union {EFI_UDP4_PROTOCOL    *Udp4;EFI_UDP6_PROTOCOL    *Udp6;} Protocol;union {EFI_UDP4_CONFIG_DATA    Udp4;EFI_UDP6_CONFIG_DATA    Udp6;} Config;
};

基本上都是与UDP(这里只关注UDP4版本),其中的Token在DoDnsQuery()中创建:

EFI_STATUS
DoDnsQuery (IN  DNS_INSTANCE  *Instance,IN  NET_BUF       *Packet)
{if (Instance->UdpIo->RecvRequest == NULL) {Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);if (EFI_ERROR (Status)) {return Status;}}

它在发送请求时使用。

EFI_DNS4_PROTOCOL

该Protocol的结构体如下:

///
/// The EFI_DNS4_Protocol provides the function to get the host name and address
/// mapping, also provides pass through interface to retrieve arbitrary information
/// from DNS.
///
struct _EFI_DNS4_PROTOCOL {EFI_DNS4_GET_MODE_DATA       GetModeData;EFI_DNS4_CONFIGURE           Configure;EFI_DNS4_HOST_NAME_TO_IP     HostNameToIp;EFI_DNS4_IP_TO_HOST_NAME     IpToHostName;EFI_DNS4_GENERAL_LOOKUP      GeneralLookUp;EFI_DNS4_UPDATE_DNS_CACHE    UpdateDnsCache;EFI_DNS4_POLL                Poll;EFI_DNS4_CANCEL              Cancel;
};

DoDnsQuery

本函数是DNS4模块中最重要的部分,其实现也比较简单:

EFI_STATUS
DoDnsQuery (IN  DNS_INSTANCE  *Instance,IN  NET_BUF       *Packet)
{//// Ready to receive the DNS response.//if (Instance->UdpIo->RecvRequest == NULL) {Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);if (EFI_ERROR (Status)) {return Status;}}//// Transmit the DNS packet.//NET_GET_REF (Packet);Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);
}

它最终调用的就是UDP4接口:

EFI_STATUS
EFIAPI
UdpIoSendDatagram (IN  UDP_IO           *UdpIo,IN  NET_BUF          *Packet,IN  UDP_END_POINT    *EndPoint OPTIONAL,IN  EFI_IP_ADDRESS   *Gateway  OPTIONAL,IN  UDP_IO_CALLBACK  CallBack,IN  VOID             *Context)
{TxToken = UdpIoCreateTxToken (UdpIo, Packet, EndPoint, Gateway, CallBack, Context);//// Insert the tx token into SendDatagram list before transmitting it. Remove// it from the list if the returned status is not EFI_SUCCESS.//InsertHeadList (&UdpIo->SentDatagram, &TxToken->Link);if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {Status = UdpIo->Protocol.Udp4->Transmit (UdpIo->Protocol.Udp4, &TxToken->Token.Udp4);}

最终的调用流程:

EFI_DNS4_PROTOCOL.HostNameToIp
Dns4HostNameToIp
DoDnsQuery
EFI_DNS4_PROTOCOL.GeneralLookUp
Dns4GeneralLookUp

这就与EFI_DNS4_PROTOCOL联系起来了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/422350.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何将一个项目整体推送到gitee上以及如何在gitee上新建一个分支,并将一个项目全部推上去

1.如何将一个项目整体推送到gitee上 在Gitee上创建一个新的仓库&#xff0c;或者选择一个已有的仓库。 在本地的项目文件夹中打开终端或命令提示符窗口。 初始化Git仓库。在终端窗口中执行以下命令&#xff1a; git init将项目所有文件添加到Git的暂存区。执行以下命令&#…

枚举问题刷题

考研机试题目中的很多问题往往能通过暴力方法来求解&#xff0c;这些题目并不需要进行过多的思考&#xff0c;而只需枚举所有可能的情况&#xff0c;或者模拟题目中提出的规则&#xff0c;便可以得到解答。虽然说这种方法看上并不高明&#xff0c;但对于一些简单的题目来说却是…

c语言小游戏之扫雷

目录 一&#xff1a;游戏设计理念及思路 二&#xff1a;初步规划的游戏界面 三&#xff1a;开始扫雷游戏的实现 注&#xff1a;1.创建三个文件&#xff0c;test.c用来测试整个游戏的运行&#xff0c;game.c用来实现扫雷游戏的主体&#xff0c;game.h用来函数声明和包含头文…

计算一个4+3的结构变换问题

4a13 3a6 1 0 0 0 0 0 0 0 1 0 0 → ← 1 1 1 0 0 1 0 0 0 0 0 0 0 1 平面上有4个点由左向右运动&#xff0c;彼此之间保持4a13的结构&#xff0c;4个点既不在同一行&#xff0c;也不在同一列。还有3个点从右向左运动&#xff0c;保持3a6的结构&a…

【LeetCode: 12. 整数转罗马数字 + 模拟 + 有序表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

springboot集成COS对象存储

1.申请腾讯云存储桶 新建密钥&#xff08;后面配置要用到&#xff09; 2.编写工具类 此处使用工具类进行基本属性配置&#xff0c;也可选择在yml中配置 package com.sfy.util;import com.qcloud.cos.COSClient; import com.qcloud.cos.ClientConfig; import com.qcloud.cos.a…

一位CSGO游戏搬砖人的自白

“阿阳&#xff0c;游戏搬砖这个项目是不是需要大量本金&#xff1f;需要花费大量的时间和精力&#xff1f;必须用到手机和电脑是吗&#xff1f;有没有只用一部手机一天花两三小时就能赚钱的项目推荐呢&#xff1f; 这是我最不喜欢听到的粉丝发来的聊天开场白。 反问一下自己…

免费在线压缩图片网站分享

支持批量压缩处理&#xff0c;但需要注意&#xff0c;网站仅仅支持体积为5MB的图片&#xff0c;压缩率高达66%&#xff0c;压缩完成后&#xff0c;点下Donwnload all&#xff0c;就能将图片保存至本地。 网页端直接进行图片压缩 https://tinify.cn/

热烈祝贺中玺汇集团《沃购拼》上市盛典圆满成功

鼓乐喧天&#xff0c;舞姿优美&#xff0c;一群用热情点燃生活的舞者拉开了上市盛典序幕。 《沃购拼》品牌应急生态平台&#xff0c;在科技与创新的驱动下&#xff0c;中玺汇集团在市场中崭露头角&#xff0c;今日我们迎来了一个历史性的时刻——中玺汇集团“沃购拼”品牌在香港…

基于线程池的TCP套接字通信

基于线程池的TCP套接字通信 还是只改变server.cpp 其中main函数, 也就是主线程中的处理流程: 创建监听的套接字绑定IP和端口设置监听创建线程池实例对象添加监听任务 acceptConn主线程退出 监听任务函数的处理流程如下: 阻塞等待并接受客户端连接检测有客户端连接时, 添加…

flutter3使用dio库发送FormData数据格式时候的坑,和get库冲突解决办法

问题描述 问题1&#xff1a;当你使用FormData.from(Flutter3直接不能用)的时候&#xff0c;可能会提示没有这个方法&#xff0c;或者使用FormData.fromMap(flutter3的dio支持)的时候也提示没有&#xff0c;这时候可能就是和get库里面的Formdata冲突了 问题1&#xff1a;The me…

【Linux】第三十二站:命名管道

文章目录 一、命名管道介绍二、编码1.mkfifo2.unlink3.一个简单的例子4.修改 一、命名管道介绍 管道应用的一个限制就是只能在具有共同祖先&#xff08;具有亲缘关系&#xff09;的进程间通信。 如果我们想在不相关的进程之间交换数据&#xff0c;可以使用FIFO文件来做这项工作…