閱讀741 返回首頁    go 阿裏雲 go 技術社區[雲棲]


網絡子係統44_ip協議源路由選項處理

//skb->pkt_type根據l2地址設置,在eth_type_trans(由驅動調用)中,如果數據幀的目的l2地址為接收接口的l2地址,設置為PACKET_HOST
//skb->rt->rt_type根據l3地址設置,在ip_route_input(由ip協議調用)中,如果數據幀的目的l3地址為本機配置的l3地址,設置為RTN_LOCAL

//調用路徑ip_rcv->ip_rcv_finish->ip_options_rcv_srr
//	1.skb->dst非本機ip,
//		1.1 嚴路由選項,向發送方返回錯誤
//		1.2 寬路由選項,直接返回,繼續ip_rcv_finish後續處理
//	2.skb->dst本機ip,
//		尋找源路由選項ptr指示的下一個,非本機ip的單播地址,複製到ip報頭,設置ip_changed使ip校驗和失效。

//根據源路由選項,選擇下一跳地址,並更新skb->dst路由緩存
1.1 int ip_options_rcv_srr(struct sk_buff *skb)
{
	struct ip_options *opt = &(IPCB(skb)->opt);//ip控製塊,在ip_options_compile中被初始化
	int srrspace, srrptr;
	u32 nexthop;
	struct iphdr *iph = skb->nh.iph;
	unsigned char * optptr = skb->nh.raw + opt->srr;
	struct rtable *rt = (struct rtable*)skb->dst;
	struct rtable *rt2;
	int err;

	if (!opt->srr)
		return 0;

	if (skb->pkt_type != PACKET_HOST)//l2地址非本機
		return -EINVAL;
	if (rt->rt_type == RTN_UNICAST) {//l3地址非本機,但是可以到達
		if (!opt->is_strictroute)//非嚴源路由選項,可以跳過,不處理
			return 0;
		icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl(16<<24));//否則通過icmp,報告發送主機,本機不在嚴路由ip列表中
		return -EINVAL;
	}
	if (rt->rt_type != RTN_LOCAL)//l3地址非主機,則返回錯誤
		return -EINVAL;
	//從ptr指示的起始位置,逐個遍曆後續的路由ip,直到下一跳為非本機單播路由
	for (srrptr=optptr[2], srrspace = optptr[1]; srrptr <= srrspace; srrptr += 4) {
		if (srrptr + 3 > srrspace) {//不足4字節
			icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((opt->srr+2)<<24));//報告錯誤
			return -EINVAL;
		}
		memcpy(&nexthop, &optptr[srrptr-1], 4);//從源路由選項中,複製下一跳的ip地址

		rt = (struct rtable*)skb->dst;
		skb->dst = NULL;
		err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev);//通過源路由選項提供的下一跳地址,路由查詢
		rt2 = (struct rtable*)skb->dst;
		if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) {//查詢出現錯誤,或者下一跳地址非單播路由,並且非指向本地的路由
			ip_rt_put(rt2);
			skb->dst = &rt->u.dst;//使用之前的路由選項
			return -EINVAL;//返回錯誤
		}
		ip_rt_put(rt);
		if (rt2->rt_type != RTN_LOCAL)//找到非本機單播地址
			break;
		memcpy(&iph->daddr, &optptr[srrptr-1], 4);//修改ip報頭的目的地址
		opt->is_changed = 1;
	}
	if (srrptr <= srrspace) {
		opt->srr_is_hit = 1;
		opt->is_changed = 1;
	}
	return 0;
}

最後更新:2017-04-03 14:53:37

  上一篇:go matlab產生萊斯分布隨機數
  下一篇:go 萊斯信道matlab建模