linux 虚拟网卡 c语言,虚拟网卡程序设计

本文介绍了如何在Linux环境下使用C语言创建和操作TUN/TAP虚拟网卡设备。首先,展示了通过`tuntap_create`函数打开TUN设备,并使用`ioctl`设置设备属性。接着,详细阐述了TUN/TAP设备的结构和驱动程序的工作原理,包括`struct tun_struct`和`struct net_device`。此外,还提供了`OpenTunAndRead.c`示例代码,演示了如何读取TUN设备的数据并进行网络包截获。最后,讨论了通过socket将数据发送给另一台主机(HA),并在HA端进行数据处理和回传的过程。
摘要由CSDN通过智能技术生成

一、创建设备并拦截数据包

1、打开虚拟设备tun   (存在opentun文件夹下)

opentun.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

/*******************代码说明***********************

打开tun/tap设备  written by fys 2012/4/18

/*******************代码说明***********************

/*

所在头文件:自定义函数

函数原型:int tuntap_create (const char *dev);

函数功能:打开TUN/TAP设备,返回设备文件描述符号

入口参数:设备名字符串,"tun"或"tap"

出口参数:设备文件描述符号

*/

int tuntap_create (const char *dev)  //dev可以是字符串“tun”,也可以是“tap”

{

struct ifreq ifr;//ifreq存放接口信息

int fd;

char *device = "/dev/net/tun";

/*打开设备文件描述*/

if ((fd = open (device, O_RDWR)) < 0)

fprintf(stderr, "Cannot open TUN/TAP dev %s", device);

/*打开设备文件描述*/

memset (&ifr,0, sizeof (ifr));

ifr.ifr_flags = IFF_NO_PI;

/*判断参数dev是何种设备*/

if (!strncmp (dev, "tun", 3))//比较dev与tun的前三个字符

{

ifr.ifr_flags |= IFF_TUN;

}

else if (!strncmp (dev, "tap", 3))

{

ifr.ifr_flags |= IFF_TAP;

}

else

{

fprintf(stderr, "I don't recognize device %s as a TUN or TAP device",dev);

}

/*判断参数dev是何种设备*/

if (strlen (dev) > 3)/* unit number specified? */

strncpy (ifr.ifr_name, dev, IFNAMSIZ);

if(ioctl(fd, TUNSETIFF, (void *)&ifr) < 0)//打开虚拟网卡

fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

if(ioctl(fd, TUNSETNOCSUM, (void *)&ifr) < 0)//不校验和

fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

fprintf(stderr, "TUN/TAP device %s opened\n", ifr.ifr_name);

return fd;//返回设备文件描述符号

}

int main()

{

tuntap_create("tun");//打开tun设备,返回tun文件描述符号

system("ifconfig tun0 up");

while(1);//使设备一直处于打开状态,死循环。

return 0;

}

opentun.sh

#!/bin/bash

#开启tun设备

gcc -o opentun.exe opentun.c

./opentun.exe

2、TUN/TAP设备结构 struct tun_struct { char name[8]; //设备名 unsigned long flags; //区分tun和tap设备 struct fasync_struct *fasync; //文件异步通知结构 wait_queue_head_t read_wait; //等待队列 struct net_device dev; //linux 抽象网络设备结构 struct sk_buff_head txq; //网络缓冲区队列 struct net_device_stats stats; //网卡状态信息结构 };

struct net_device结构是linux内核提供的统一网络设备结构,定义了系统统一的访问接口。

Tun/tap驱动中实现的网卡驱动的处理例程:

static int tun_net_open(struct net_device *dev);

static int tun_net_close(struct net_device *dev);

static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev);//数据包发送例程

static void tun_net_mclist(struct net_device *dev);//设置多点传输的地址链表

static struct net_device_stats *tun_net_stats(struct net_device *dev);//当一个应用程序需要知道网络接口的一些统计数据时,可调用该函数,如ifconfig、netstat等。

int tun_net_init(struct net_device *dev);//网络设备初始例程

字符设备部分:

在Linux中,字符设备和块设备统一以文件的方式访问,访问它们的接口是统一的,都是使用open()函数打开设备文件或普通文件,用read()和write()函数实现读写文件等等。Tun/tap驱动定义的字符设备的访问接口如下:

static struct file_operations tun_fops = {

owner: THIS_MODULE,

llseek: tun_chr_lseek,

read tun_chr_read,

write: tun_chr_write,

poll: tun_chr_poll,

ioctl: tun_chr_ioctl,

open: tun_chr_open,

release: tun_chr_close,

fasync: tun_chr_fasync

};

在内核中利用misc_register() 函数将该驱动注册为非标准字符设备驱动,提供字符设备具有的各种程序接口。代码摘自linux-2.4.20\linux-2.4.20\drivers\net\tun.c static struct miscdevice tun_miscdev= { TUN_MINOR, "net/tun", &tun_fops }; int __init tun_init(void) { … if (misc_register(&tun_miscdev)) { printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR); return -EIO; } return 0; }

3、

截获发往某个地址的数据

OpenTunAndRead.c

#include <stdio.h>

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

/*****

虚拟网卡驱动源代码(原版): /* * snull.c -- the Simple Network Utility * * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly & Associates * * The source code in this file can be freely used, adapted, * and redistributed in source or binary form, so long as an * acknowledgment appears in derived source files. The citation * should list that the code comes from the book "Linux Device * Drivers" by Alessandro Rubini and Jonathan Corbet, published * by O'Reilly & Associates. No warranty is attached; * we cannot take responsibility for errors or fitness for use. * * $Id: snull.c,v 1.21 2004/11/05 02:36:03 rubini Exp $ */ #include #include #include #include #include #include /* printk() */ #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include /* struct tcphdr */ #include #include "snull.h" #include #include MODULE_AUTHOR("Alessandro Rubini, Jonathan Corbet"); MODULE_LICENSE("Dual BSD/GPL"); /* * Transmitter lockup simulation, normally disabled. */ static int lockup = 0; module_param(lockup, int, 0); static int timeout = SNULL_TIMEOUT; module_param(timeout, int, 0); /* * Do we run in NAPI mode? */ static int use_napi = 0; module_param(use_napi, int, 0); /* * A structure representing an in-flight packet. */ struct snull_packet { struct snull_packet *next; struct net_device *dev; int datalen; u8 data[ETH_DATA_LEN]; }; int pool_size = 8; module_param(pool_size, int, 0); /* * This structure is private to each device. It is used to
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值