libnetfilter_queue:修改数据后未正确计算ICMP校验和

时间:2016-04-17 16:29:51

标签: c linux icmp

该程序处理ICMP消息队列(系统ping)。我需要修改接收的数据(函数swap_bytes - 下面的代码)并重新计算ICMP校验和。所以我有一个类似的回调函数:

static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
                struct nfq_data *nfa, void *data) {

u_int32_t id; /* ID packet. */
unsigned short checksum;
int payload_len;
unsigned char *payloadData;
struct icmphdr *icmp_header; 

/* Some informations about the packet: */
//id = print_packet(nfa);
//fprintf(stdout, "Leaving callback.\n\n");

/* Modification */
payload_len = nfq_get_payload(nfa, &payloadData);
icmp_header = (struct icmphdr *)payloadData;
swap_bytes(payloadData, payload_len);
icmp_header->checksum = 0;
checksum = internet_checksum(   
                (unsigned short *)&icmp_header, 
                payload_len+sizeof(struct icmphdr)
                                    );
icmp_header->checksum = (checksum == 0) ? 0xffff : checksum;

/* verdict */
return nfq_set_verdict(qh, id, NF_ACCEPT, payload_len, payloadData); 
}

swap_bytes函数:

unsigned char* swap_bytes(unsigned char *data, unsigned int data_length) {

unsigned char tmp;
unsigned char *head, *tail;

head = data;
tail = &data[data_length - 1];

while (head < tail) {
    tmp = *head;
    *head = *tail;
    *tail = tmp;
    head++;
    tail--;
}

return data;
}

计算校验和:

unsigned short internet_checksum(unsigned short *addr, int count) {

register int sum = 0;

while (count > 1) {
    sum += *addr++;
    count -= 2;
}

if (count > 0) {
    sum +=   *(unsigned char *) addr;
}

while (sum >> 16) {
    sum = (sum & 0xffff) + (sum >> 16);
}

return (~sum);
}

问题是校验和计算不正确,因为我没有收到ICMP回复。我尝试了很多没有结果的方法。谢谢你的帮助。

0 个答案:

没有答案