转换从TUN接口接收的原始分组数据

时间:2014-06-10 14:11:21

标签: c networking tun

我正在尝试拦截通过TUN接口的数据包。 我想将原始数据包信息转换为可读信息,以便我以后可以使用它。

我正在使用以下代码:

int main(){
    char tun_name[IFNAMSIZ];
    char data[1500];
    int nread = 0;
    int tun_fd = 0;

    /* Connect to the device */
    strcpy(tun_name, "tun1");
    tun_fd = tun_alloc(tun_name);  /* tun interface, no Ethernet headers*/
    if(tun_fd < 0){
        perror("Allocating interface");
        exit(1);
    }

    /* Now read data coming from the kernel */
    int i=0;
    int count=0;
    char src[INET_ADDRSTRLEN];
    u_int8_t protocol;

    while(1) {
        count ++;

        nread = read(tun_fd, data, sizeof(data));
        if(nread < 0) {
            perror("Reading from interface");
            close(tun_fd);
            exit(1);
        }

        struct ip *iphdr = (struct ip *) data;

        /* Do whatever with the data */
        printf("Packet N° %d\n", count);
        printf("Read %d bytes from device %s\n", nread, tun_name);

        protocol = iphdr->ip_p;
        inet_ntop(AF_INET, &(iphdr->ip_src), src, INET_ADDRSTRLEN);

        printf("\nProtocol: %d", protocol);
        printf("\nIP source address: %s", src);
        printf("\n\n");
    }
    return 0;
}

似乎我无法读取数据包的协议和ip src地址。我得到了令人满意的结果。

你能帮忙吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

问题在于这一行:

tun_fd = tun_alloc(tun_name);  /* tun interface, no Ethernet headers*/

这是函数tun_alloc()的定义:

int tun_alloc(char *dev) {

    struct ifreq ifr;
    int fd, err;
    char *clonedev = "/dev/net/tun";

    /* open the clone device */
    if( (fd = open(clonedev, O_RDWR)) < 0 ) {
        return fd;
    }

    /* preparation of the struct ifr, of type "struct ifreq" */
    memset(&ifr, 0, sizeof(ifr));

    ifr.ifr_flags = IFF_TUN;   /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */

    if (*dev) {
        strncpy(ifr.ifr_name, dev, IFNAMSIZ);
     }

    /* try to create the device */
    if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
        close(fd); 
    return err;
    }
    strcpy(dev, ifr.ifr_name);
    return fd;

}

在这里,在创建TUN接口时,我们必须使用“IFF_NO_PI”标志来删除数据包添加信息并仅接收原始数据包。

所以,我们必须使用它:

ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 

而不只是:

ifr.ifr_flags = IFF_TUN; 

希望它有所帮助,谢谢。