Click here to Skip to main content
15,171,053 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
For some reason, I need to put/inject a packet to an interface. I've made the content of the packet in the local machine. Assume that there's no other machine in the network to send the packet to local machine's network interface. So the local machine should do the job. If I send the packet to the interface, it's be put to the interface for going out of the machine and since the destination MAC address of the packet and the destination IP of the packet belong to the local machine, the packet will go nowhere. I think such a packet is called an egress packet, while I need the same packet be received by the interface or pretend for the kernel that it has been received by the interface. I think such a packet is called an ingress packet. OS is ubuntu 20.04 and the code is in C. An example of such a code follows. I've examined it between two VM's and it works perfectly, but what can I do when I want to do it with only one machine?

In the following example, I respond the ping (ICMP) packets. When I run it between two VM's it works properly, but when I send the generated response to the only interface in a single machine, the ping can't get its response.

int main(int argc, const char *argv[])
    u8 buf[1000], *dest = NULL;
    int len, destLen = 0;

    int sdRaw = OpenRawSocket(argv[1], NULL, NULL);
    while (true)
        len = recv(sdRaw, buf, sizeof(buf), 0);
        CHECK(len > 0, "%s", strerror(errno));
        if (*(u16 *)(buf + 0x0c) == 8 &&
            buf[0x17] == 1)
            if (destLen < len)
                printf("destLen: %d --> %d\n", destLen, len);
                dest = realloc(dest, len);
                destLen = len;
            memcpy(dest + 12, buf + 12, len - 12);
            memcpy(dest, buf + 6, 6);
            memcpy(dest + 6, buf, 6);
            *(u16 *)(dest + 0x14) = 0;
            *(u32 *)(dest + 0x1a) = *(u32 *)(buf + 0x1e);
            *(u32 *)(dest + 0x1e) = *(u32 *)(buf + 0x1a);
            //dest[0x22] = 0;  // no need
            FixChecksums(dest, len);
            CHECK(send(sdRaw, dest, len, 0) == len, "%s", strerror(errno));

Please don't ask about the usefulness of the code. I'm going to simplify the issue with a simple code, but the problem will be resolved if this simple issue will be overcomed.

What I have tried:

It's weird that all questions are forced to have a portion for the questioner to describe what they've tried. Some questions are just questions, not some trial and effort issues. They may be just in the beginning of a problem and don't know the first step.
Richard MacCutchan 5-May-21 10:07am
If you want to send a message back to the same machine then you should use the loopback IP address which is normally
ilostmyid2 5-May-21 10:35am
If I use the loopback interface, I'll get the same packet on recv. I need to process the sent packet and change it as you see in the code so that recv will receive what I've generated or modified from the interface. For this, loopback interface may not be useful for this purpose.
Richard MacCutchan 5-May-21 11:23am
Sorry, that is the only way I know how to do it.
Gerry Schmitz 6-May-21 12:52pm
You "receive" before sending. Not a typical exchange when it's usually call-and-response.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900