1

下面是 linux kernel 3.4 第 51 和 52 行中的 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}
4

1 回答 1

4

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

类型(1 字节) | 长度(1 字节)| 偏移量(1 字节) | ...然后是一些地址,每个地址 4 个字节

LENGTH“字段”指定整个选项的字节长度,这就是为什么 iph[opt->srr+1] 是选项的长度。

于 2012-12-07T08:16:28.080 回答