全部博文(436)
分类: LINUX
2010-10-29 17:30:13
ICMP差错报文的格式
不可达,超时,源泉抑制
type |
len |
cksum |
Void(必须是0) |
被破坏分组的IP首部 |
需要分片
type |
len |
cksum |
Pmvoid(必须是0) |
nextmtu |
被破坏分组的IP首部 |
参数问题
type |
len |
cksum |
pptr |
(必须是0) |
被破坏分组的IP首部 |
信宿不可达报文类型表
代码值 |
类型描述 |
|
代码值 |
类型描述 |
0 |
网络不可达 |
|
7 |
信宿主机未知 |
1 |
主机不可达 |
|
8 |
信源主机被隔离 |
2 |
协议不可达 |
|
9 |
与信宿网络的通信被禁止 |
3 |
端口不可达 |
|
10 |
与信宿主机的通信杯禁止 |
4 |
需要分片和DF设置 |
|
11 |
对请求的服务类型,网络不可达 |
5 |
源路由失败 |
|
12 |
对请求的服务类型,主机不可达 |
6 |
信宿网络未知 |
|
|
|
/* Handle ICMP_UNREACH and ICMP_QUENCH. */处理ICMP_UNREACH和ICMP_QUENCH。//处理不可达和源终止//
static void
icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb) ;//调用icmp_unreach函数类型3
{
struct inet_protocol *ipprot;
struct iphdr *iph; //定义IP头部
unsigned char hash;
int err;//定义变量
err = (icmph->type << 8) | icmph->code;// ICMP包类型为8,响应请求
iph = (struct iphdr *) (icmph + 1);//IP的头标位ICMP的头标加1
switch(icmph->code & 7) //将icmph指向代码(为8位)并与7与后进行判断,得到不可达类型的代号
{
case ICMP_NET_UNREACH://当网络不可达时
DPRINTF((DBG_ICMP, "ICMP: %s: network unreachable.\n",
in_ntoa(iph->daddr))); //输出网络不可访问的目的IP地址
break;
case ICMP_HOST_UNREACH: //当主机不可达时
DPRINTF((DBG_ICMP, "ICMP: %s: host unreachable.\n",
in_ntoa(iph->daddr))); //输出主机不可访问 目的IP地址
break;
break;
case ICMP_PROT_UNREACH://当端口不可达时
printk("ICMP: %s:%d: protocol unreachable.\n",
in_ntoa(iph->daddr), ntohs(iph->protocol));
//输出ICMP协议不可达 目的IP地址 协议首地址
break;
case ICMP_PORT_UNREACH:
DPRINTF((DBG_ICMP, "ICMP: %s:%d: port unreachable.\n",
in_ntoa(iph->daddr), -1 /* FIXME: ntohs(iph->port) */));
break;????
case ICMP_FRAG_NEEDED://当需要分片时和DF设置时
printk("ICMP: %s: fragmentation needed and DF set.\n",
in_ntoa(iph->daddr));//输出碎片需要和DF设置 目的IP地址
break;
case ICMP_SR_FAILED://当源路由失败时
printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
break;// 目的IP地址 源路由失败
default:
DPRINTF((DBG_ICMP, "ICMP: Unreachable: CODE=%d from %s\n",
(icmph->code & 7), in_ntoa(iph->daddr)));
break;
}
//若不是上述情况 则输出DBG_ICMP icmp不可达 code的值 目的ip地址
/* Get the protocol(s). *///获取通讯协定
hash = iph->protocol & (MAX_INET_PROTOS -1);
//hash等于iph->protocol并(MAX_INET_PROTOS -1)
/* This can change while we are doing it. */
ipprot = (struct inet_protocol *) inet_protos[hash];//如果找到相关的协议
while(ipprot != NULL) {
struct inet_protocol *nextip;//到路由的下一跳
nextip = (struct inet_protocol *) ipprot->next;// ipprot 等于inet的协议 inet_protos[hash],ipprot不为空,ipprot等于 inet的协议 *,ipprot指向下一个值
/* Pass it off to everyone who wants it. */
if (iph->protocol == ipprot->protocol && ipprot->err_handler) {
ipprot->err_handler(err, (unsigned char *)(icmph + 1),
iph->daddr, iph->saddr, ipprot);
}//
ipprot = nextip;
}
skb->sk = NULL;
kfree_skb(skb, FREE_READ);