如果我填充了 iphdr 的所有字段,那么如何计算 tcphdr->doff 和 iphdr->ihl | tcp 数据偏移量和 ip 长度 header

if I have populated all fields of iphdr then how to calculate the tcphdr->doff and iphdr->ihl | tcp data offset and length of ip header

在我的系统中 /usr/include/netinet/iphdr 这是 iphdr 结构看起来像

struct iphdr
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ihl:4;
    unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
    unsigned int version:4;
    unsigned int ihl:4;
#else
# error "Please fix <bits/endian.h>"
#endif
    uint8_t tos;
    uint16_t tot_len;
    uint16_t id;
    uint16_t frag_off;
    uint8_t ttl;
    uint8_t protocol;
    uint16_t check;
    uint32_t saddr;
    uint32_t daddr;
    /*The options start here. */
  };

假设我已经制作了所有具有值的 ip header 字段。现在我想计算 ip header 长度,它是我系统上的 iphdr->ihl 字段。我假设这是 ip header 长度,所以我制作的 ip header 的长度不能是 sizeof(struct iphdr) 那可能是什么。

另外 struct tcphdr 看起来像这样

struct tcphdr
  {
    __extension__ union
    {
      struct
      {
    uint16_t th_sport;  /* source port */
    uint16_t th_dport;  /* destination port */
    tcp_seq th_seq;     /* sequence number */
    tcp_seq th_ack;     /* acknowledgement number */
# if __BYTE_ORDER == __LITTLE_ENDIAN
    uint8_t th_x2:4;    /* (unused) */
    uint8_t th_off:4;   /* data offset */
# endif
# if __BYTE_ORDER == __BIG_ENDIAN
    uint8_t th_off:4;   /* data offset */
    uint8_t th_x2:4;    /* (unused) */
# endif
    uint8_t th_flags;
# define TH_FIN 0x01
# define TH_SYN 0x02
# define TH_RST 0x04
# define TH_PUSH    0x08
# define TH_ACK 0x10
# define TH_URG 0x20
    uint16_t th_win;    /* window */
    uint16_t th_sum;    /* checksum */
    uint16_t th_urp;    /* urgent pointer */
      };
      struct
      {
    uint16_t source;
    uint16_t dest;
    uint32_t seq;
    uint32_t ack_seq;
# if __BYTE_ORDER == __LITTLE_ENDIAN
    uint16_t res1:4;
    uint16_t doff:4;
    uint16_t fin:1;
    uint16_t syn:1;
    uint16_t rst:1;
    uint16_t psh:1;
    uint16_t ack:1;
    uint16_t urg:1;
    uint16_t res2:2;
# elif __BYTE_ORDER == __BIG_ENDIAN
    uint16_t doff:4;
    uint16_t res1:4;
    uint16_t res2:2;
    uint16_t urg:1;
    uint16_t ack:1;
    uint16_t psh:1;
    uint16_t rst:1;
    uint16_t syn:1;
    uint16_t fin:1;
# else
#  error "Adjust your <bits/endian.h> defines"
# endif
    uint16_t window;
    uint16_t check;
    uint16_t urg_ptr;
      };
    };
};

所以再次假设我已经用值填充了 tcphdr 的所有字段,现在我想要 doff(数据偏移量)。如何计算

  struct iphdr *iph=buffer;
   // populate the fields of iph
   //but what is iph->ihl? to calculate how?
   int iphdrlen = iph->ihl*4;
   struct tcphdr *tcph=(struct tcphdr *)(buffer + iphdrlen);
   //populate all the fields of tcph
   //but also how to calculate tcph->doff

是否应该像 iphdr->ihl

//after populating all the fields of iph then  just do following to get iph->ihl

  iph->ihl=sizeof(iph);

它应该像 tcph->doff

 //after populating all the fields of tcph just do following

  tcph->doff = (unsigned int)(sizeof(iph))+sizeof(tcph)));

这行得通,那行吗?

IP header 有两个“部分”——强制固定大小的部分,由 struct iphdr 表示,后者由 可选 [=30= 的选项表示] 可以存在(参见评论 /*The options start here. */)。 header 长度是带选项的整个 header 长度。因此,除非您实际添加了一些选项,否则它只是 header 的长度,您可以在 standard:

中计算或读取它

IHL: 4 bits

Internet Header Length is the length of the internet header in 32 bit words, and thus points to the beginning of the data. Note that the minimum value for a correct header is 5.

现在一个字节是4位,32位是4个字。因此它可以是 sizeof(struct iphdr)/4 或者你可以将它设置为 5.

TCP数据偏移量基本相同,只是针对TCP。由于 TCP header 也可以包含选项,因此适用相同的逻辑。根据 standard(滚动到下一页):

Data Offset: 4 bits

The number of 32 bit words in the TCP Header. This indicates where the data begins. The TCP header (even one including options) is an integral number of 32 bits long.

所以,基本上是这样计算的。它不是一个指针,它是一个表示header长度的数字。根据wikipedia如果你的header没有选项,这个字段的值也是5.