Linux内核ip_options_build()函数

Linux内核ip_options_build()函数

问题描述:

下面是在Linux内核3.4,线51和52的ip_options_build():Linux内核ip_options_build()函数

51  if (opt->srr) 
52    memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4); 

据我所知,两行说,如果源路由选项存在,复制目的地地址到选项末尾,这表明iph [opt-> srr + 1]是源路由选项的长度,但我不明白为什么?

31/* 
32 * Write options to IP header, record destination address to 
33 * source route option, address of outgoing interface 
34 * (we should already know it, so that this function is allowed be 
35 * called only after routing decision) and timestamp, 
36 * if we originate this datagram. 
37 * 
38 * daddr is real destination address, next hop is recorded in IP header. 
39 * saddr is address of outgoing interface. 
40 */ 
41 
42void ip_options_build(struct sk_buff *skb, struct ip_options *opt, 
43      __be32 daddr, struct rtable *rt, int is_frag) 
44{ 
45  unsigned char *iph = skb_network_header(skb); 
46 
47  memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options)); 
48  memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen); 
49  opt = &(IPCB(skb)->opt); 
50 
51  if (opt->srr) 
52    memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4); 
53 
54  if (!is_frag) { 
55    if (opt->rr_needaddr) 
56      ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, skb, rt); 
57    if (opt->ts_needaddr) 
58      ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, skb, rt); 
59    if (opt->ts_needtime) { 
60      struct timespec tv; 
61      __be32 midtime; 
62      getnstimeofday(&tv); 
63      midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC  
+   tv.tv_nsec/NSEC_PER_MSEC); 
64      memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4); 
65    } 
66    return; 
67  } 
68  if (opt->rr) { 
69    memset(iph+opt->rr, IPOPT_NOP, iph[opt->rr+1]); 
70    opt->rr = 0; 
71    opt->rr_needaddr = 0; 
72  } 
73  if (opt->ts) { 
74    memset(iph+opt->ts, IPOPT_NOP, iph[opt->ts+1]); 
75    opt->ts = 0; 
76    opt->ts_needaddr = opt->ts_needtime = 0; 
77  } 
78} 

如果我没记错,iph + opt-> srr基本上是srr选项第一个字节的地址。选项本身的格式如下:

TYPE(1字节)|长度(1字节)| OFFSET(1字节)| ...然后一些地址每个4字节

LENGTH“field”指定整个选项的长度(以字节为单位),所以这就是为什么iph [opt-> srr + 1]是选项的长度。