昨天晚上突然想到这个东西,今天花了一上午实现了!不过具体速度怎么样就不清楚了!
首先是目的!一个系统上的鼠标去控制另一个系统。通过网线连接。
方案!在一个系统上获取鼠标信息网传到另一个系统,接受信息的系统通过input机制上报。
对于网传的接受,你可以在用户层去做,我是在内核层去做的,参考我之前搞的vnic代码。我就不废话了,直接代码:
/*
*/
#include <linux/capability.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/rculist.h>
#include <net/p8022.h>
#include <net/arp.h>
#include <net/ip.h>
#include <linux/rtnetlink.h>
#include <linux/notifier.h>
#include <net/rtnetlink.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <asm/uaccess.h>
#include <linux/etherdevice.h>
#include <linux/ip.h>
#include <linux/usb/input.h>
#include "vnic.h"
#define DRV_VERSION "1.0"
/* End of global variables definitions. */
static void vnic_group_free(struct vnic_group *grp)
{
int i;
for (i = 0; i < VNIC_GROUP_ARRAY_SPLIT_PARTS; i++)//释放所有已申请的虚拟网卡
kfree(grp->vnic_devices_arrays[i]);
kfree(grp);//释放一个vnic_group结构
}
static struct vnic_group *vnic_group_alloc(void)
{
struct vnic_group *grp;
grp = kzalloc(sizeof(struct vnic_group), GFP_KERNEL);//申请一个vnic_group结构
if (!grp)
return NULL;
return grp;
}
static int vnic_group_prealloc_vid(struct vnic_group *vg, u16 vnic_id)
{
struct net_device **array;
unsigned int size;
array = vg->vnic_devices_arrays[vnic_id / VNIC_GROUP_ARRAY_PART_LEN];//这样是为了多组设计的,其实我就一组
if (array != NULL)
return 0;
size = sizeof(struct net_device *) * VNIC_GROUP_ARRAY_PART_LEN;//一组有8个
array = kzalloc(size, GFP_KERNEL);
if (array == NULL)
return -ENOBUFS;
vg->vnic_devices_arrays[vnic_id / VNIC_GROUP_ARRAY_PART_LEN] = array;
return 0;
}
static struct net_device *real_netdev = NULL;
static struct vnic_group *vnic_grp = NULL;
static struct input_dev *input_dev = NULL;
static int vnic_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev)
{
#if 0
struct net_device *vnic_dev;
struct vnic_pcpu_stats *rx_stats;
u16 vnic_id = skb->data[1];//这部就相当于解析我们自己的头
#if 1
u16 i;
for (i = 0; i < skb->mac_len; i++)
{
printk("%x ", skb->mac_header[i]);
}
printk("\n");
#endif
vnic_dev = vnic_group_get_device(vnic_grp, vnic_id);
if (vnic_dev == NULL)
{
return -1;
}
//检查skb的应用计数是否大于1,大于1意味着内核的其他部分拥有对
//该缓冲区的引用。如果大于1,会自己建立一份缓冲区副本。
skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb))
{
return false;
}
skb->dev = vnic_dev;
//PACKET_OTHERHOST表示L2目的地址和接收接口的地址不同
//通常会被丢弃掉。如果网卡进入混杂模式,会接收所以包
//这里我们就要自己比较一下。
if (skb->pkt_type == PACKET_OTHERHOST) {
if (!compare_ether_addr(eth_hdr(skb)->h_dest, vnic_dev->dev_addr))
skb->pkt_type = PACKET_HOST;
}
rx_stats = (struct vnic_pcpu_stats *)this_cpu_ptr(vnic_dev_info(vnic_dev)->vnic_pcpu_stats);
u64_stats_update_begin(&rx_stats->syncp);
rx_stats->rx_packets++;
rx_stats->rx_bytes += skb->len;
if (skb->pkt_type == PACKET_MULTICAST)
rx_stats->rx_multicast++;
u64_stats_update_end(&rx_stats->syncp);
#else
__u16 type;
__u16 code;
//__s8 value;
type = skb->data[0] | (skb->data[1] << 8);
code = skb->data[2] | (skb->data[3] << 8);
if (type == 1)
{
switch(code)
{
case BTN_LEFT:
input_report_key(input_dev, BTN_LEFT, skb