解组以太网帧和数据对齐

时间:2012-11-18 07:42:40

标签: c parsing header ethernet unmarshalling

所以我试图解组以太网帧eth和ip header。我有一个程序框架,它从文件读取输入数据,并为我提供框架数据的结构。

我已经google了,并阅读了有关该主题的其他帖子,但我无处可去。例如: Data Alignment with network programming http://en.wikipedia.org/wiki/Data_structure_alignment

我不确定问题是什么。显然我是C的新手。

如果我只是尝试使用memcpy并将数据复制到我的eth和ip标头的结构中,大多数数据都很好,但不是我的ip结构中的ip地址。我也尝试从1byte,2byte和4byte块中读取输入结构,但它没有给我正确的数据。

以下是输入文件中输入数据框的示例:

200 0000 0002 0200 0000 0012 0800 4500 0026 17d4 81e7 ff01 0000 0a02 0002 0c0c 0c0c 0000 e802 c04b 0004 3e89 3325 0006 ddef 0809

以下是使用

的标题结构
struct ethhdr{
    char     da[6];
    char     sa[6];
    uint16_t pt;
};
typedef struct ethhdr ethhdr;

struct iphdr{
#ifdef WORDS_BIGENDIAN
    unsigned int ip_v:4;        /* version */
    unsigned int ip_hl:4;       /* header length */
#else
    unsigned int ip_hl:4;       /* header length */
    unsigned int ip_v:4;        /* version */
#endif 
    uint8_t  ip_tos;            /* type of service */
    uint16_t ip_len;            /* total length */
    uint16_t ip_id;         /* identification */
    uint16_t ip_off;            /* fragment offset field */
    uint8_t  ip_ttl;            /* time to live */
    uint8_t  ip_p;          /* protocol */
    uint16_t ip_sum;            /* checksum */
    uint32_t ip_src, ip_dst;            /* source and dest address */
};
typedef struct iphdr iphdr;

即将投放的输入数据结构。

struct fe_context{
    char   *pkt;         /* Pointer to packet */
    size_t  len;         /* Length of packet */
    void   *if_in;       /* Incoming interface - handle */
};
typedef struct fe_context fe_context;

我如何依赖于读取数据的示例代码。

int fe_process(fe_context *c)
{
  printf("\n\nPacket received!\n");
  printf("memcpy to header structs:\n");
  ethhdr * ethh = (ethhdr *) malloc(sizeof(ethhdr));
  iphdr * iph = (iphdr *) malloc(sizeof(iphdr));
  memcpy(ethh, c->pkt, sizeof(ethhdr));
  memcpy(iph, c->pkt+sizeof(ethhdr), sizeof(ethhdr));

  printf("MAC SA: %02x:%02x:%02x:%02x:%02x:%02x\n", ethh->sa[0], ethh->sa[1], ethh->sa[2], 
      ethh->sa[3], ethh->sa[4], ethh->sa[5]);
  printf("MAC P: %04x\n", ntohs(ethh->pt));

  printf("IP Ver: %x\n", ntohl(iph->ip_v));
  printf("IP IHL: %x\n", ntohl(iph->ip_hl));
  printf("IP TTL: %i\n", iph->ip_ttl);
  printf("IP Checksum: %x\n", ntohl(iph->ip_sum));
  printf("IP SRC: %08x\n", ntohl(iph->ip_src));
  printf("IP DST: %08x\n", ntohl(iph->ip_dst));

  char * cp = c->pkt;
  printf("\nPacket read by char:\n");
  char data;
  int p;
  for(p = 0; p < 52; p++) {
    data = *cp;
    cp++;
    printf("%02x", data);
    if(p%2==1) {
      printf(" ");
    }
  }
  printf("\n\n");
  cp = c->pkt;
  printf("Packet read by uint16_t:\n");
  uint16_t data16;
  for(p = 0; p < 52/2; p++) {
    data16 = *cp;
    cp+=2;
    printf("%04x ", ntohs(data16));
  }
  printf("\n\n");
  cp = c->pkt;
  printf("Packet read by uint32_t:\n");
  uint32_t data32;
  for(p = 0; p < 52/4; p++) {
    data32 = *cp;
    cp+=4;
    printf("%08x ", ntohl(data32));
  }
  printf("\n\n");

  return 0;
}

这是输出上面的测试数据。

Packet received!
memcpy to header structs:
MAC SA: 02:00:00:00:00:12
MAC P: 0800
IP Ver: 4000000
IP IHL: 5000000
IP TTL: 255
IP Checksum: 0
IP SRC: 0a020000
IP DST: 00000000 // It looks good up until here. this should be 0c0c0c0c

Packet read by char:
0200 0000 0002 0200 0000 0012 0800 4500 0026 17ffffffd4 ffffff81ffffffe7 ffffffff01 0000 0a02 0002 0c0c 0c0c 0000 ffffffe802 ffffffc04b 0004 3effffff89 3325 0006 ffffffddffffffef 0809 

Packet read by uint16_t:
0200 0000 0000 0200 0000 0000 0800 4500 0000 1700 81ff ffff 0000 0a00 0000 0c00 0c00 0000 e8ff c0ff 0000 3e00 3300 0000 ddff 0800 

Packet read by uint32_t:
02000000 00000000 00000000 08000000 00000000 81ffffff 00000000 00000000 0c000000 e8ffffff 00000000 33000000 ddffffff 

正如您所看到的那样,结构中的数据一直很好,直到DST IP。这可能是因为填充/数据对齐?通过查看char读取,看起来问题会以某种方式发生在数据的ip头部分?当我读到char时,这些'f'来自哪里?

我尝试检查c-&gt; pkt指针地址及其偶数。我甚至不确定这是否重要?我认为它将永远是因为malloc为我做到了。什么是正确的方式来读取这些数据进行解析/解组?我将对这些数据进行更改,因此我希望将数据转换为整齐的结构。

我的代码中是否有一个简单的错误,或者我的方法是错误的?非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

我注意到你在线上犯了一个错误:

memcpy(iph, c->pkt+sizeof(ethhdr), sizeof(ethhdr));

您正在为您的IP标头而不是sizeof(ethhdr)复制sizeof(iphdr)个字节,这是您想要的。好像你输错了。