加入收藏 | 设为首页 | 会员中心 | 我要投稿 三明站长网 (https://www.0598zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核分析 - 网络[十四]:IP选项

发布时间:2016-09-28 22:37:56 所属栏目:Linux 来源:站长网
导读:副标题#e# 内核版本:2.6.34 在发送报文时,可以调用函数setsockopt()来设置相应的选项,本文主要分析IP选项的生成,发送以及 接收所执行的流程,选取了LSRR为例子进行说明,主要分为选项的生成、选项的转发、选项的接收三部分。 先看一个源站路 由选项的例

首先会作一些检查,选项长度optlen不能比3 小,到少有3字节的头部:code, len, ptr。指针ptr不能比4小,因为头部就有4字节。这里optlen是去除了头部的IPOPT_NOOP后 的长度,而ptr的计算是包括IPOPT_NOOP的,因此一个是3一个是4;另外,选项中只能有一个源路由选项,因此当srr有值时,表 示正在处理的是第二个源路由选项,则有错误。

if (optlen < 3) {     
 pp_ptr = optptr + 1;     
 goto error;     
}     
if (optptr[2] < 4) {     
 pp_ptr = optptr + 2;     
 goto error;     
}     
/* NB: cf RFC-1812 5.2.4.1 */ 
if (opt->srr) {     
 pp_ptr = optptr;     
 goto error;     
}

当skb==NULL,对应于第一种情况(生成报文选项时);取出源路由选项的第一跳,记录到选项opt的faddr中,作为下 一跳地址;源路由选项依次前移。对应于开头给出的例子,这里处理后结果如图所示:

if (!skb) {     
 if (optptr[2] != 4 || optlen < 7 || ((optlen-3) & 3)) {     
  pp_ptr = optptr + 1;     
  goto error;     
 }     
 memcpy(&opt->faddr, &optptr[3], 4);     
 if (optlen > 7)     
  memmove(&optptr[3], &optptr[7], optlen-7);     
}

Linux内核分析 - 网络[十四]:IP选项

最后 记录,is_strictroute是否是严格的路由选路,srr表示选项到IP报头的距离,同样,它只对处理收到的报文中选项时有效。

opt->is_strictroute = (optptr[0] == IPOPT_SSRR);     
opt->srr = optptr - iph;

以上是关于IP选项报文的生成,下面从ip_rcv()来看IP选项报文的接收。

ip_rcv() -> ip_rcv_finish()

ip_rcv()中重置IP的控制数据struct inet_skb_param为0,在IP章节已经说过,控制数据是skb中48 字节的一个字段,在各层协议中含义不同,在IP层,它被解释为inet_skb_parm,包含opt和flags,其中前者与IP选项有关。

memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));     
struct inet_skb_parm {     
 struct ip_options opt;  /* Compiled IP options  */ 
 unsigned char  flags;     
};

ip_rcv_finish()中如果头部长度字段ihl大于4,则表示含有IP选项,此时调用ip_rcv_optins()来接收IP选项。

if (iph->ihl > 5 && ip_rcv_options(skb))     
 goto drop;

ip_rcv_options()

iph指向IP头;opt指向控制数据的opt,对IP选项处理的结构会存放在此,作为skb 的一部分,在其它地方起作用;设置opt->optlen选项长度,这里的长度包括了开头的IPOPT_NOOP字段,是4的整数倍。

iph = ip_hdr(skb);     
opt = &(IPCB(skb)->opt);     
opt->optlen = iph->ihl*4 - sizeof(struct iphdr);

调用ip_options_compile()处理选项,这是该函数被调 用的第二种情况(收到带IP选项报文时),传入参数skb是报文的skb,函数的详细说明见上文(还是以LSRR为例),实际上 ip_options_compile()在这种情况下只相应设置了opt->is_strictroute和opt->srr,而不像在生成选项时对IP选项进行 处理,对接收到IP选项的处理要留带到发送报文时。

if (ip_options_compile(dev_net(dev), opt, skb)) {     
 IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);     
 goto drop;     
}

如果是LSRR,opt->srr在上一步中被设置,为选项到报头的距离,对于带SSRR或LSRR选项的报文来说,opt- >srr值不为0,进入调用ip_options_rcv_srr()完成LSRR选项的处理。

if (unlikely(opt->srr)) {     
 ……     
 if (ip_options_rcv_srr(skb))     
  goto drop;     
}     
return 0;

ip_options_rcv_srr()

该函数的主要作用是根据源站选项重新设置skb的路由项,从而改变报文的正常流 程。它不会对选项进行其它操作,真正的操作在发送时完成。

首先会进行一些检查,报文的目的MAC必须是本主机,这里检查 skb->pkt_type==PACKET_HOST;如果报文的目的IP不是本机(而是在本机的邻居),则本主只是源路径的一个中转站,此时不 用再次查找路由表,直接返回,这里检查rt->rt_type==RTN_UNICAST,这种情况在LSRR中是允许的,SSRR是不允许的;如果 报文的目的IP对本机来说不是直接可达,则错误返回。

if (skb->pkt_type != PACKET_HOST)     
 return -EINVAL;     
if (rt->rt_type == RTN_UNICAST) {     
 if (!opt->is_strictroute)     
  return 0;     
 icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl(16<<24));     
 return -EINVAL;     
}     
if (rt->rt_type != RTN_LOCAL)     
 return -EINVAL;

(编辑:三明站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读