简体   繁体   中英

How to read packet by packet from linux tun/tap

I have connected to an existing Tap device using

fd = open(...)

Now i want to read from it packet by packet. if i use

read(fd,buffer,sizeof(buffer));

I wont read exactly 1 packet.

How can i read exactly 1 packet? Is there some kind of header that says the packet length or in the worst case i will have to parse the packet and figure the length myself?

I was wrong about the way read() reads bytes from a tap device. It turns out when I use read() it reads exactly 1 frame, (or n bytes if n is smaller then frame size)

Libpcap: http://www.tcpdump.org/pcap3_man.html

You can read packets coming in through whatever interface you specify, in this example its wlan1.

int main(){
    char *device = NULL;
    pcap_t* descr;

     if(argc > 0)
       device = "wlan1";

    if(device == NULL)
    {
      printf("%s\n",errbuf);
      exit(1);
    }
    descr = pcap_open_live(device,BUFSIZ,0,-1,errbuf);

    if(descr == NULL){ printf("pcap_open_live(): %s\n",errbuf); exit(1); }

    errbuf[0] = 0;
    handle = pcap_open_live(device, BUFSIZ,1,0,errbuf);

    pcap_loop(handle,-1, process_packet, NULL);
    pcap_close(handle);
    return 0;
  }

Where in pcap_loop the process_packet is the callback of the packets coming in.

Let me know if there is anything you are unsure of.


PS Here is some links that should help you with parsing 802.11/ethernet headers.

http://madwifi-project.org/wiki/DevDocs/RadiotapHeader http://yuba.stanford.edu/~casado/pcap/section2.html http://www.cacetech.com/documents/PPI%20Header%20format%201.0.7.pdf

This is how I parse packets from a raw layer3 network stream.

#include "bigendian.h"

#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>


int pb_packet_read(PacketBuffer *b, int fd, int count, PacketCallback cb) {
    int i = 0;
    int result;
    Packet *p;
    unsigned char *start;
    size_t remaining;

    while (i < count) {
        if (b->packet == NULL) {
            if (b->level < 20 ) {
                // Read up to MTU bytes to determine packet header.
                result = read(fd, b->blob + b->level, MTU - b->level);
                if (result <= 0) {
                    return i;
                }
                b->level += result;
            }

            if (b->level < 20 ) {
                return i;
            }

            // Now, can read the packet total length
            start = b->blob;
            p = (Packet*) malloc(sizeof(Packet));
            p->start = start;
            p->version = start[0] >> 4;
            p->total_length = bigendian_deserialize_uint16(start + 2);
            memcpy(&(p->src.s_addr), start + 12, 4);
            memcpy(&(p->dst.s_addr), start + 16, 4);

            b->packet = p;


        }
        else {
            L_DEBUG("Using prev stored complete packet.");
            p = b->packet;
        }

        // Read the rest of the packet
        if (p->total_length > b->level) {
            remaining = p->total_length - b->level;
            L_DEBUG("Packet not completed, trying read more.");
            result = read(fd, b->blob + b->level, remaining);

            if(result <= 0) {
                if (result == EAGAIN) {
                    L_DEBUG("EAGAIN");
                }
                perror("READ BODY");
                return i;
            }
            b->level += result;
            if (result < remaining) {
                L_DEBUG("Not enough data");
                return i;
            }
        }

        if (b->level > p->total_length) {
            remaining = b->level - p->total_length;
            memcpy(b->blob, b->blob + p->total_length, remaining);
            b->level = remaining;
            L_DEBUG("Remaining data: %lu", remaining);
        }

        // Packet is ready to pass to callback.
        if(cb) {
            cb(p);
        }

        // Cleanup for the next packet
        i++;
        b->level = 0;
        free(b->packet);
        b->packet = NULL;
    }
    return i;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM