Here is the situation: in my scenario I have, 3 computers, A, B and C.
Computer A sends data to computer B. Computer B captures these packets with pcap, appends the headers, redoes the checksums, and injects it out another ethernet interface to computer C. So basically A sends to C, though through C’s point of view, the data is coming from computer B.
My problem is this: following TCPDUMP’s tutorial on dissecting a captured packet, I’ve learned to calculate offsets and using typecasting to obtain ethernet, ip, and tcp header structures. The method of doing so is shown below:
ethernet = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
size_ip = IP_HL(ip)*4;
if (size_ip < 20) {
printf(" * Invalid IP header length: %u bytes\n", size_ip);
return;
}
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
size_tcp = TH_OFF(tcp)*4;
if (size_tcp < 20) {
printf(" * Invalid TCP header length: %u bytes\n", size_tcp);
return;
}
payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
Because I want to inject the captured packet to send it from computer B to computer C, I must modify some of the source/destination information and recalculate the checksum when I’m done. However, my issue is, since this data is now separated into structures of ethernet header, IP header, and TCP headers, how do I put it back together into a u_char that pcap_inject can use?
Is it possible to do some sort of concatenation here?
From the code I see here, you’re not actually dissecting the memory that
libpcapcaptured for you. Each of the casting operations simply tells the compiler how you intend to treat the bytes starting from a pointer — what size those objects are, what offsets to find which pieces of data and how long they are.If you modify this memory through those pointers, you’ve modified the one and only copy of it in the process memory — and can use some of the “more basic” pointers to hand the entire block of memory to
sendmsg(2)or whatever without needing to reassemble the data — you never took it apart.Update
To inject the packets back on the network you need to use the
raw(7)socket type; theIPPROTO_RAWsocket option is required to send TCP packets through araw(7)socket — otherwise, all TCP packets would be directed to theraw(7)socket you open, making networking on the machine difficult to use.The
raw(7)sockets will perform some re-calculation tasks for you:Let the kernel re-calculate whatever it is willing to do for you.