网络子系统50_ip协议选项填充

//调用路径ip_queue_xmit->ip_options_build
//函数主要任务:
//	1.非分片ip报文,向ip报头填充ip选项,ip选项在创建socket时设置
//	2.分片ip报文,将record route选项,time stamp选项设置为NOP
//	daddr,ip接收方的地址
1.1 void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
			    u32 daddr, struct rtable *rt, int is_frag)
{
	unsigned char * iph = skb->nh.raw;

	memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options));//将socket中提供的ip选项拷贝到skb->cb中
	memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen);//复制ip选项到ip报头后
	opt = &(IPCB(skb)->opt);
	opt->is_data = 0;

	if (opt->srr)//将目标地址拷贝到源路由选项列表中的最后一个位置上
		memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4);

	if (!is_frag) {//在ip_queue_xmit->ip_options_build调用路径上,is_frag为0
		if (opt->rr_needaddr)//record route选项
			ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, rt);//获取路由的首选源地址填充到选项ptr所指的位置
		if (opt->ts_needaddr)//time stamp选项
			ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt);
		if (opt->ts_needtime) {
			struct timeval tv;
			__u32 midtime;
			do_gettimeofday(&tv);//通过do_gettimeofday获取系统时间,填充当天的ms
			midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
			memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4);
		}
		return;
	}
	//ip分片中的选项
	if (opt->rr) {
		memset(iph+opt->rr, IPOPT_NOP, iph[opt->rr+1]);//设置record route为NOP
		opt->rr = 0;
		opt->rr_needaddr = 0;
	}
	if (opt->ts) {
		memset(iph+opt->ts, IPOPT_NOP, iph[opt->ts+1]);//设置time stamp为NOP
		opt->ts = 0;
		opt->ts_needaddr = opt->ts_needtime = 0;
	}
}
时间: 2024-08-31 16:48:40

网络子系统50_ip协议选项填充的相关文章

网络子系统48_ip协议数据帧的发送

//ip协议与l4协议接口,l4通过此接口向下l3传递数据帧 //函数主要任务: // 1.通过路由子系统路由封包 // 2.填充l3报头 // 3.ip分片 // 4.计算校验和 // 5.衔接邻居子系统,向下层传送封包. 1.1 int ip_queue_xmit(struct sk_buff *skb, int ipfragok) { struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); struct ip_opt

网络子系统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非

网络子系统42_ip协议数据帧的接收

//参考 深入理解linux网络技术内幕                                      // 注册l3协议 // ptype_all链表,链接所有ETH_P_ALL类型的l3协议 // ptype_base哈希表,非ETH_P_ALL类型的l3协议 // 注:l3协议可以使用相同的协议号 1.1 void dev_add_pack(struct packet_type *pt) { int hash; //ptype_all ptype_base共用一把锁 ptype

网络子系统56_ip协议分片重组_重组分片

//调用路径ip_defrag->ip_frag_reasm // 所有ip分片都被接收到时,重组ip数据包 // 判断ip所有分片都接收到的条件: // 1.FIRST_IN, LAST_IN // 2.meat = len,即 根据offset推断出的最大封包长度等于已接收到的封包长度 // 重组过程: // 1.将sk_buff链表从ipq->fragments取下 // 2.将第一个分片以后的分片挂在第一个分片的frag_list域 // 3.从分片子系统使用内存中减去该ip数据包的内

网络子系统36_BPDU协议格式

//参考 深入理解linux网络技术内幕 //通过以太网帧的目的地址,判断一个数据帧是否为bpdu数据帧 //1.BPDU封装格式:                                          //2.区分BPDU类型为CONFIG还是TCN,CONFIG类型的BPDU封包长38字节,TCN类型的BPDU封包长度为7字节 //由上图,越过以太网帧头6+6+2+3(llc头),之后为bpdu协议内容,偏移量为3的一个字节,指示封包为CONFIG或TCN            

网络子系统46_ip协议数据帧的转发

// ip协议数据转发 // ip_forward以回调函数的形式,保存在skb->dst->input,skb->dst在ip_route_input路由封包时被设置 // 调用路径:ip_rcv->ip_rcv_finish->dst_input->(skb->dst->input) // 函数的主要任务: // 1.递减ttl // 2.如果路由被重定向,则向发送方发送icmp重定向报文 // 2.如果有选项,通过ip_forward_options处

网络子系统51_ip协议报文分片

//ip分片 // 快速路径的条件: // 1.skb // 1.skb的数据长度(主缓存区+frags缓存区)小于输出路径的mtu // 2.skb的数据长度对齐到8字节的边界 // 3.skb没有被分片 // 4.skb没有被共享 // 2.skb->frag_list // 1.长度小于(mtu-ip报头-选项) // 2.除最后一个分片外,长度都需要对齐到8字节边界 // 3.head-data之间的空间,可以容纳ip报头 // 注:skb->frag_list的skb,没有填充ip头

网络子系统86_inet协议族-l4向下(一)

// l4数据向下l3传递 // 步骤: // 1.如果sock->sk_write_queue为空,初始化corking // 1.1 corking信息用于帮助ip层对数据进行分片 1.1 int ip_append_data(struct sock *sk, struct flowi4 *fl4, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from,

网络子系统80_inet协议族-SOCK_RAW(一)

// SOCK_RAW 1.1 static struct inet_protosw inetsw_array[] = { ... { .type = SOCK_RAW, .protocol = IPPROTO_IP, /* 通配符 */ .prot = &raw_prot, /* Networking protocol blocks attached to sockets */ .ops = &inet_sockraw_ops, .no_check = UDP_CSUM_DEFAULT,