数据字段可选,但是在请求回显消息中接收到的数据必须在回显应答消息中返回 。(即是同一对回显的数据必须一致)
10.5 ICMP数据结构lwip支持的icmp数据结构在icmp.h
文件中 。
10.5.1 ICMP数据报数据结构数据结构:
/** This is the standard ICMP header only that the u32_t data *is split to two u16_t like ICMP echo needs it. *This header is also used for other ICMP types that do not *use the data part. */PACK_STRUCT_BEGINstruct 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;PACK_STRUCT_END
操作:
#define ICMPH_TYPE(hdr) ((hdr)->type) // 读取类型字段#define ICMPH_CODE(hdr) ((hdr)->code) // 读取代码字段#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) // 设置类型字段#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) // 设置代码字段
10.5.2 ICMP类型字段#define ICMP_ER0/* 回显回答 */#define ICMP_DUR3/* 目的不可达 */#define ICMP_SQ4/* 源站抑制 */#define ICMP_RD5/* 重定向 */#define ICMP_ECHO 8/* 回显请求 */#define ICMP_TE11/* 数据报超时 */#define ICMP_PP12/* 数据报参数错误 */#define ICMP_TS13/* 时间戳请求 */#define ICMP_TSR 14/* 时间戳回答 */#define ICMP_IRQ 15/* 信息请求 */#define ICMP_IR16/* 信息回答 */#define ICMP_AM17/* 地址掩码请求 */#define ICMP_AMR 18/* 地址掩码回答 */
10.5.3 目的不可达代码字段/** ICMP目的不可达代码字段 */enum icmp_dur_type {/** 网络不可达 */ICMP_DUR_NET= 0,/** 主机不可达 */ICMP_DUR_HOST= 1,/** 协议不可达 */ICMP_DUR_PROTO = 2,/** 端口不可达 */ICMP_DUR_PORT= 3,/** 需要分片但不分片置位 */ICMP_DUR_FRAG= 4,/** 源路由失败 */ICMP_DUR_SR= 5};
10.5.4 超时代码字段/** ICMP超时代码字段 */enum icmp_te_type {/** 生存时间超时值TTL为0 */ICMP_TE_TTL= 0,/** 分片数据报重装超时 */ICMP_TE_FRAG = 1};
10.6 发送ICMP差错报告10.6.1 发送ICMP差错报文基函数icmp_send_response()
函数就是发送ICMP差错报文的基函数,可以封装这个函数实现各种ICMP差错报文 。
该函数主要逻辑:
- 检查触发ICMP差错报告的IP报文pbuf中的数据size是否符合要求 。
- 目的不可达的ICMP差错报文一般需要IP首部+8字节数据 。
- 申请ICMP差错报文pbuf资源 。
- 组装ICMP数据报 。
- 路由匹配网卡 。
- 通过IP层输出函数发送ICMP报文 。
/** * Send an icmp packet in response to an incoming packet. * * @param p the input packet for which the 'unreachable' should be sent, *p->payload pointing to the IP header * @param type Type of the ICMP header * @param code Code of the ICMP header */static voidicmp_send_response(struct pbuf *p, u8_t type, u8_t code){struct pbuf *q; /* ICMP差错报文pbuf指针 */struct ip_hdr *iphdr; /* 触发ICMP差错报告的IP头指针 */struct icmp_echo_hdr *icmphdr; /* ICMP报文首部指针 */ip4_addr_t iphdr_src; /* 触发ICMP差错报告的IP源地址 */struct netif *netif; /* 发送ICMP差错报告的网卡 */u16_t response_pkt_len; /* ICMP数据区长度 *//* 增加试图发送的消息数 */MIB2_STATS_INC(mib2.icmpoutmsgs);/* IP头+8 */response_pkt_len = IP_HLEN + ICMP_DEST_UNREACH_DATASIZE;if (p->tot_len < response_pkt_len) { /* 如果触发ICMP差错报告的IP报文pbuf数据区不够8,就全部上传即可 。*/response_pkt_len = p->tot_len;}/* 申请ICMP差错报告的pbuf资源,长度为ICMP差错报告首部+数据区*/q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + response_pkt_len, PBUF_RAM);if (q == NULL) {LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));MIB2_STATS_INC(mib2.icmpouterrors);return;}LWIP_ASSERT("check that first pbuf can hold icmp message",(q->len >= (sizeof(struct icmp_echo_hdr) + response_pkt_len)));iphdr = (struct ip_hdr *)p->payload; /* 提取IP报文首部 */LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src);LWIP_DEBUGF(ICMP_DEBUG, (" to "));ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest);LWIP_DEBUGF(ICMP_DEBUG, ("\n"));icmphdr = (struct icmp_echo_hdr *)q->payload;icmphdr->type = type; /* 设置ICMP类型字段 */icmphdr->code = code; /* 设置ICMP代码字段 */icmphdr->id = 0; /* 设置ICMP标识字段 */icmphdr->seqno = 0; /* 设置ICMP序号字段 *//* 拷贝触发ICMP差错的IP报文首部+(<=8)字节的原数据到ICMP差错报告数据区 */SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,response_pkt_len);ip4_addr_copy(iphdr_src, iphdr->src); /* 提取IP源地址 */#ifdef LWIP_HOOK_IP4_ROUTE_SRC{ip4_addr_t iphdr_dst;ip4_addr_copy(iphdr_dst, iphdr->dest); /* 提取IP目的地址 */netif = ip4_route_src(&iphdr_dst, &iphdr_src); /* 路由匹配网卡 */}#elsenetif = ip4_route(&iphdr_src); /* 路由匹配网卡 */#endifif (netif != NULL) { /* 匹配网卡成功 */icmphdr->chksum = 0; /* ICMP校验和字段 */#if CHECKSUM_GEN_ICMPIF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) {icmphdr->chksum = inet_chksum(icmphdr, q->len); /* 计算ICMP校验和 */}#endifICMP_STATS_INC(icmp.xmit);/* 通过指定网卡把ICMP报文转交到IP层发送出去 */ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif);}/* 释放ICMP报文资源 */pbuf_free(q);}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 创造与魔法2022最新礼包在哪里领取
- 奥比岛手游被频繁投诉的是哪支施工队
- 琉璃神社app有苹果的吗
- 用什么方式打开.dll文件(电脑怎么打开dll文件)
- cmd如何运行dll(运行dll命令)
- Sql Server性能排查和优化懒人攻略
- lol烬的大招怎么放,技巧是什么(lol烬的技能介绍)
- lol英雄联盟戏命师烬大招怎么放(lol手游烬大招怎么释放)
- 在 .NET 7上使用 WASM 和 WASI
- 【lwip】09-IPv4协议&超全源码实现分析