我正在通過IP過濾器攔截,修改和重新注入傳出的IPv4 TCP數據包。 問題是,在我改變數據包並設置IP和TCP校驗和後,當我用Wireshark分析結果數據包時,IP校驗和等於0(我正在計算的校驗和似乎是正確的,因爲它等於Wireshark的建議一個)。macOS NKE ipf_filter - IP校驗和爲0
這裏是我下面的步驟,我希望有一個人誰可以當場錯誤或提出處理事情有更好的方式:
static int handle_packet(mbuf_t* data, int ip_len, int dir, ipf_pktopts_t options)
{
errno_t result = 0;
unsigned char packet[1500];
struct tcphdr *tcp;
struct ip *ip;
mbuf_t old_packet = *data, new_packet;
uint32_t mbufs = 0, packet_bytes = 0;
// zero packet
bzero(packet, sizeof(packet));
// "finalize" the packet so that it is safe to modify it
mbuf_outbound_finalize(*data, AF_INET, 0);
// get length of mbuf chain
do
{
mbufs++;
packet_bytes += mbuf_len(old_packet);
old_packet = mbuf_next(old_packet);
} while (old_packet != NULL);
// copy data to local buffer
if (0 != (result = mbuf_copydata(*data, 0, packet_bytes, packet))) {
printf("mbuf_copydata returned %d", result);
return 0;
}
// pointer to start IP header
ip = (struct ip*)packet;
tcp = (struct tcphdr*)((u_int32_t*)ip + ip->ip_hl);
// only consider SYN packet
if (!(tcp->th_flags & TH_SYN))
return KERN_SUCCESS;
if (0 != (result = mbuf_dup(*data, MBUF_DONTWAIT, &new_packet)))
{
printf("ERROR - mbuf_dup: unable to duplicate mbuf, %d", result);
return 0;
}
/**
… I’m modifying the packet and recalculating ip and tcp’s checksums here
(by previously setting them to 0, so to avoid that the previous values
are considered in the calculation) …
*/
/*
* Copy buffer back to mbuf
*/
if (0 != (result = mbuf_copyback(new_packet, 0, ntohs(ip->ip_len), packet, MBUF_DONTWAIT)))
{
mbuf_freem(new_packet);
switch (result) {
case EINVAL:
printf("ERROR - handle_packet: mbuf_copyback returned EINVAL");
return 0;
break;
case ENOBUFS:
printf("ERROR - handle_packet: mbuf_copyback returned ENOBUFS");
return 0;
break;
default:
break;
}
}
// recompute any checksums invalidated by data changes
// mbuf_outbound_finalize(new_packet, AF_INET, 0); // -> PANIC(m->m_flags & M_PKTHDR)
// is this necessary?
mbuf_set_csum_performed(new_packet, MBUF_CSUM_DID_IP | MBUF_CSUM_IP_GOOD | MBUF_CSUM_DID_DATA | MBUF_CSUM_PSEUDO_HDR, checksum_ip(ip));
result = ipf_inject_output(new_packet, ip_filter_ref, options);
return result == 0 ? EJUSTRETURN : result;
}
static errno_t ip_filter_output(void* cookie, mbuf_t *data, ipf_pktopts_t options)
{
struct ip *ip;
char src[32], dst[32];
int ip_len;
// pointer to start IP header
ip = (struct ip*)mbuf_data(*data);
ip_len = ntohs(ip->ip_len);
bzero(src, sizeof(src));
bzero(dst, sizeof(dst));
// converts the network address structure into a character string
inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src));
inet_ntop(AF_INET, &ip->ip_dst, dst, sizeof(dst));
// avoid congestion and filter only packets from/to tcpcrypt website
if (ip->ip_p == IPPROTO_TCP
&& mbuf_flags(*data) == MBUF_PKTHDR) {
return handle_packet(data, ip_len, DIRECTION_OUT /* 1 */, options);
}
// continue with normal processing of the packet
return KERN_SUCCESS;
}
我懷疑越來越零是重新計算的預期後果整個頭部的校驗和,即它導致計算出的總和自行消失。
無論如何,我真的不明白爲什麼會發生這種情況。
有沒有人知道答案或可以幫助?
非常感謝你提前,
羅密歐
他正在調用'mbuf_outbound_finalize()',請參閱該方法的文檔。不管你的硬件是否卸載,都調用這個函數來保證正確的校驗和。從文檔:「*有許多操作是在硬件中執行的,例如計算校驗和。這個函數將在軟件中執行計劃在硬件中完成的各種操作。*」所以你的回答沒有意義,我不明白爲什麼這是被接受的答案。 – Mecki