Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2175742
  • 博文数量: 436
  • 博客积分: 9833
  • 博客等级: 中将
  • 技术积分: 5558
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-29 10:27
文章存档

2013年(47)

2012年(79)

2011年(192)

2010年(118)

分类: LINUX

2010-10-29 20:53:17

/* Deal with incoming ICMP packets.处理传入的ICMP数据包  接收icmp*/

int

icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,

     unsigned long daddr, unsigned short len,

     unsigned long saddr, int redo, struct inet_protocol *protocol)

{

  struct icmphdr *icmph;

  unsigned char *buff;

 

  /* Drop broadcast packets. 丢弃掉广播包/

  if (chk_addr(daddr) == IS_BROADCAST) {//如果目的地是本地I广播包

    DPRINTF((DBG_ICMP, "ICMP: Discarded broadcast from %s\n",

                            in_ntoa(saddr)));//分辨是否为自己IP地址

    skb1->sk = NULL;

    kfree_skb(skb1, FREE_READ);

    return(0);//如果不是,将该包释放

  }

 

  buff = skb1->h.raw;

  icmph = (struct icmphdr *) buff;

 

/* Validate the packet first */首先验证包的合法性.

  if (ip_compute_csum((unsigned char *) icmph, len)) {

    /* Failed checksum! */校验和失败!

    printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));//校验和不等于源主机的校验和

    skb1->sk = NULL;

    kfree_skb(skb1, FREE_READ);//释放该包

    return(0);

  }

print_icmp(icmph);

 

 /* Parse the ICMP message */解析ICMP消息

  switch(icmph->type) {

    case ICMP_TIME_EXCEEDED: //超时

    case ICMP_DEST_UNREACH://不可达

    case ICMP_SOURCE_QUENCH://源抑制

        icmp_unreach(icmph, skb1);

        return(0);

    case ICMP_REDIRECT://重定向

        icmp_redirect(icmph, skb1, dev);

        return(0);

    case ICMP_ECHO: //ECHO请求

        icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);

        return 0;

    case ICMP_ECHOREPLY://EHCO应答

        skb1->sk = NULL;

        kfree_skb(skb1, FREE_READ);

        return(0);

    case ICMP_INFO_REQUEST://信息请求

        icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);

        return 0;

    case ICMP_INFO_REPLY://信息应答

        skb1->sk = NULL;

        kfree_skb(skb1, FREE_READ);

        return(0);

    case ICMP_ADDRESS: //地址掩码请求

        icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);

        return 0;

    case ICMP_ADDRESSREPLY://地址掩码应答

        skb1->sk = NULL;

        kfree_skb(skb1, FREE_READ);

        return(0);

    default:

        DPRINTF((DBG_ICMP,

            "ICMP: Unsupported ICMP from %s, type = 0x%X\n",

                        in_ntoa(saddr), icmph->type));

        skb1->sk = NULL;

        kfree_skb(skb1, FREE_READ);

        return(0);

  }

  /*NOTREACHED*/

  skb1->sk = NULL;

  kfree_skb(skb1, FREE_READ);

  return(-1);

}

 

 

 

/* Perform any ICMP-related I/O control requests. */执行任何ICMP的相关的I / O控制请求

int

icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)

{

  switch(cmd) {判断CMD

    case DDIOCSDBG: 如果cmd确定是DDIOCSDBG 这个I/O

        return(dbg_ioctl((void *) arg, DBG_ICMP)); 则返回DBG_IP

    default:

        return(-EINVAL);否则返回错误

  }

  return(0);

ioctl对设备进行了判断,对I/O设备进行管理

}

 

功能:处理来到的ICMP数据包。

1.增加ICMP统计的入报文记数

2.如果入参len小于ICMP头结构大小,增加ICMP统计的接收错误报文记数,调用NETDEBUG,指明报文不完整,以FREE-READ为参释放skb空间,返回0

3.如果计算校验和失败,增加ICMP统计的接收错误报文记数,调用NETDEBUG,指明校验和出错,以FREE-READ为参释放skb空间,返回0

4.如果类型大于18,增加ICMP统计的接收错误报文记数,以FREE-READ为参释放skb空间,返回0

5.若定义了透明代理,条件为入参目标地址不等于设备协议地址但是广播或多播地址;

否则,条件为入参目标地址不等于设备协议地址且不是本机地址:

A.若类型不是ECHO,增加接收(IN)错误统计记数,以FREE-READ为参释放skb空间,返回0slientl ignore

B.否则,将入参目标地址置为设备协议地址。

       6.增加对应icmp_pointers表项的input计数,调用它的处理器函数,返回0

阅读(2125) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~