C结构对齐和网络协议头

时间:2013-10-28 22:40:44

标签: c struct alignment c-preprocessor

Solaris 10 SPARC
Sun Studio C 编译器12.3

在SPARC64计算机上,如果访问在相关的4或8字节边界上未正确对齐的变量,您将获得核心转储。这需要编码人员跳过几个环节来应对这个要求,(但也会让你编写可移植的代码)。

如果我们有一个 C 结构模拟网络协议头,(即这16位是一个端口,这8位是标志等),如果我们然后使用对齐指令来适应SPARC64处理器,这仍然会保留字节映射,否则会破坏一切。是否存在逻辑隐藏结构布局中字节存储的实现。

typedef struct TCPHdr_
{
    uint16_t th_sport;  /**< source port */
    uint16_t th_dport;  /**< destination port */
    uint32_t th_seq;    /**< sequence number */
    uint32_t th_ack;    /**< acknowledgement number */
    uint8_t th_offx2;   /**< offset and reserved */
    uint8_t th_flags;   /**< pkt flags */
    uint16_t th_win;    /**< pkt window */
    uint16_t th_sum;    /**< checksum */
    uint16_t th_urp;    /**< urgent pointer */
} TCPHdr;

像这样对齐:

typedef struct TCPHdr_
{
    uint16_t th_sport    __attribute__((aligned(8))); /**< source port */
    uint16_t th_dport    __attribute__((aligned(8))); /**< destination port */
    uint32_t th_seq      __attribute__((aligned(8))); /**< sequence number */
    uint32_t th_ack      __attribute__((aligned(8))); /**< acknowledgement number */
    uint8_t th_offx2     __attribute__((aligned(8))); /**< offset and reserved */
    uint8_t th_flags     __attribute__((aligned(8))); /**< pkt flags */
    uint16_t th_win      __attribute__((aligned(8))); /**< pkt window */
    uint16_t th_sum      __attribute__((aligned(8))); /**< checksum */
    uint16_t th_urp      __attribute__((aligned(8))); /**< urgent pointer */
} TCPHdr;

主要是关于这样的代码的查询:

SET_PKT_LEN(p, sizeof(IPV6Hdr) + sizeof(TCPHdr) + payload_len);

p1->tcph = (TCPHdr *)raw_tcp;

其中原始字节转换为结构或sizeof()测试结构的大小。它仍然有效还是新结构无法映射网络字节?

2 个答案:

答案 0 :(得分:0)

您可以将未对齐的结构转换为其对齐的版本,但数据可能是错误的。您需要手动将数据放入内存中的正确位置。例如。函数* unaligned_to_aligned *可以按字段复制数据。它可以使用联合来避免核心转储。 处理来自网络的原始数据时,请考虑endianness。网络协议和您的平台可以在内存中具有不同的数字表示,您可能必须更改* int * s,* short * s等中的字节顺序。

答案 1 :(得分:0)

为了记录,这是我正在使用的结构:

typedef struct TCPHdr_raw_ {
    union {
        uint16_t   th_sport;     /**< source port */
        uint8_t    th_sport8[2]; /**< source port */
    } sport;
    union {
        uint16_t   th_dport;     /**< destination port */
        uint8_t    th_dport8[2]; /**< destination port */
    } dport;
    union {
        uint32_t    th_seq;      /**< sequence number */
        uint8_t     th_seq8[4];  /**< sequence number */
    } seq;
    union {
        uint32_t    th_ack;      /**< acknowledgement number */
        uint8_t     th_ack8[4];  /**< acknowledgement number */
    } ack;
    uint8_t         th_offx2;    /**< offset and reserved */
    uint8_t         th_flags;    /**< pkt flags */
    union {
        uint16_t    th_win;      /**< pkt window */
        uint8_t     th_win8[2];  /**< pkt window */
    } win;
    union {
        uint16_t    th_sum;       /**< checksum */
        uint8_t     th_sum8[2];   /**< checksum */
    } sum;
    union {
        uint16_t    th_urp;       /**< urgent pointer */
        uint8_t     th_urp8[2];   /**< urgent pointer */
    } urp;
} TCPHdr_raw;

typedef struct TCPHdr_
{
    uint16_t th_sport  __attribute__((aligned(8))); /**< source port */
    uint16_t th_dport  __attribute__((aligned(8))); /**< destination port */
    uint32_t th_seq    __attribute__((aligned(8))); /**< sequence number */
    uint32_t th_ack    __attribute__((aligned(8))); /**< acknowledgement number */
    uint8_t th_offx2   __attribute__((aligned(8))); /**< offset and reserved */
    uint8_t th_flags   __attribute__((aligned(8))); /**< pkt flags */
    uint16_t th_win    __attribute__((aligned(8))); /**< pkt window */
    uint16_t th_sum    __attribute__((aligned(8))); /**< checksum */
    uint16_t th_urp    __attribute__((aligned(8))); /**< urgent pointer */
} TCPHdr;

和这样的例程:

copy_raw_tcp_header(&(p->tcph), &tcph);

void copy_raw_tcp_header(TCPHdr *tcph, uint8_t *pktdata) {
    TCPHdr_raw *raw_tcp_hdr = (TCPHdr_raw *)pktdata;

    memcpy(&tcph->sport,  &raw_tcp_hdr->sport.th_sport8, sizeof(uint16_t));
    memcpy(&tcph->dport,  &raw_tcp_hdr->dport.th_dport8, sizeof(uint16_t));
    memcpy(&tcph->seq,    &raw_tcp_hdr->seq.th_seq8,     sizeof(uint32_t));
    memcpy(&tcph->ack,    &raw_tcp_hdr->ack.th_ack8,     sizeof(uint32_t));
    tcph->th_offx2       = raw_tcp_hdr->th_offx2;
    tcph->th_flags       = raw_tcp_hdr->th_flags;
    memcpy(&tcph->th_win, &raw_tcp_hdr->win.th_win8,     sizeof(uint16_t));
    memcpy(&tcph->th_sum, &raw_tcp_hdr->sum.th_sum8,     sizeof(uint16_t));
    memcpy(&tcph->th_urp, &raw_tcp_hdr->urp.th_urp8,     sizeof(uint16_t));
}

替换以前的代码:

p->tcph = &tcph;