Problem in reading packets from tunnel using read()

141 Views Asked by At

I have been trying to receive and process the packets from tunnel. There are separate blocks for processing v4 and v6 packets. If the packet does not fall under the either of the categories, they will be dropped. For me, every packets are being dropped during execution. When I used wireshark to capture the packets from the tunnel, I noticed the difference in packet size, i.e., length of the packet. For example, when the length of a received packet in Wireshark is 60 whereas the program prints it 64 as length. I noticed the 4 bytes difference in all packets. I am unable to find out, what I am doing wrong here? Would anyone help me. I also attached the screen of wireshark and program execution for perusal.

Image: Captured packets from tunnel through wireshark and program

#define MTU 1600
void processPacket(const uint8_t *packet, const size_t len) {
    //1st octet identifies the IP version
    uint8_t version = (*packet) >> 4;
    //...

    printf("IP version - %d\n", version);
    if (version == 4 ) {
        //ipv4 packet process ...
    } else if (version == 6) {
        //ipv6 packet process ...
    } else {
        //drop packet
        printf("Unknown IP version, drop packet\n");
    }
}

int main() {
    struct ifreq ifr;
    int fd;
    uint8_t *buffer = (uint8_t *)(malloc(MTU));
    ssize_t len;

    if ( (fd = open("/dev/net/tun", O_RDWR)) == -1 ) {
        perror("Unable to open /dev/net/tun");
        exit(EXIT_FAILURE);
    }
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TUN;
    strncpy(ifr.ifr_name, "tun0", IFNAMSIZ);

    if ( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1 ) {
        perror("Error encountered during ioctl TUNSETIFF");
        close(fd);
        exit(EXIT_FAILURE);
    }

    printf("Device tun0 opened\n");
    while(1) {
        len = read(fd, buffer, MTU);
        printf("Read %lu bytes from tun0\n", len);
        processPacket(buffer, len);
    }

    printf("\nPress any key to exit...");
    getchar();
    close(fd);
}
1

There are 1 best solutions below

0
On BEST ANSWER

The tunnel device pre-pends the IP packet with additional information, so the first byte is not the IP version. If you don't need it, you can add IFF_NO_PI to ifr_flags. See kernel documentation.