Skip to content

ICMP协议

网络层的一个协议, 起到对IP协议辅助的功能

ICMP协议是一个网络层协议。 一个新搭建好的网络,往往需要先进行一个简单的测试,来验证网络是否畅通;但是IP协议并不提供可靠传输。如果丢包了,IP协议并不能通知传输层是否丢包以及丢包的原因。因此我们需要ICMP协议来完成这样的功能

  • 存在的原因
  1. IP 协议本身不提供差错报告和差错控制机制来保证数据报递交的有效性,例如:数据报在网络中被丢弃了,源主机更希望等到该数据报递交过程中的异常信息
  2. IP 协议不能进行主机管理与查询机制,例如:不知道对方主机或者路由器的活跃,对于不活跃的主机和路由器就没有必要发送数据报。

包含两部分, 差错报文, 以及ping, 从而实现有效的转发数据报以及提高成功的机会

image-20240708192624552

  • 差错报文

image-20240708192710563

LWIP实现的是绿色的部分

  • 查询报文

image-20240708192935819

image-20240708193534225

数据格式

c
struct icmp_echo_hdr {
  PACK_STRUCT_FLD_8(u8_t type);			//类型
  PACK_STRUCT_FLD_8(u8_t code);			//代码
  PACK_STRUCT_FIELD(u16_t chksum);		//校验和
  PACK_STRUCT_FIELD(u16_t id);			//标志位
  PACK_STRUCT_FIELD(u16_t seqno);		//序号
} PACK_STRUCT_STRUCT;

image-20240708194332731

发送

错误报文

lwIP只实现目的不可达、超时差错报文,它们分别为icmp_dest_unreach和icmp_time_exceeded函数, 最后的发送使用函数icmp_send_response

image-20240708210814243

4字节是以太网首部以及IP首部

c
/**
 * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0.
 *
 * @param p the input packet for which the 'time exceeded' should be sent,
 *          p->payload pointing to the IP header
 * @param t type of the 'time exceeded' packet
 */
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{
  MIB2_STATS_INC(mib2.icmpouttimeexcds);
  icmp_send_response(p, ICMP_TE, t);
}

最后使用函数icmp_send_response进行发送, 获取一个pbuf, 之后把收获pbuf里面的前一部分数据进行拷贝, 然后添加头部, 同时从收获的pbuf里面获取对方的IP地址

接收

查询报文

对方发送的数据不需要更改, 改变一下ICMP头部即可

image-20240708212758992

使用函数icmp_input函数

在ip4_input这一个函数里面会获取接收的pbuf里面的IP头部中的类型, 如果是ICMP, 调用icmp_input

icmp_input函数里面, 判断一下, 是回送请求的时候改一下类型, 以及改变IP首部, 之后ip4_output_if函数进行发送

image-20240708215302725

发送的时候IP地址为NULL, 所以不会再次添加首部