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()
测试结构的大小。它仍然有效还是新结构无法映射网络字节?
答案 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;