网卡驱动10-做一个与外界交互的虚拟网卡6(突发奇想!搞个网络鼠标!)

本文介绍了一个创新想法,通过网卡驱动将一个系统的鼠标控制信息传输到另一个系统,实现跨系统的鼠标操作。作者在Linux内核层处理接收和发送,提供了一段内核模块代码及用户端测试程序,展示了该功能的实际效果。
摘要由CSDN通过智能技术生成

昨天晚上突然想到这个东西,今天花了一上午实现了!不过具体速度怎么样就不清楚了!

首先是目的!一个系统上的鼠标去控制另一个系统。通过网线连接。

方案!在一个系统上获取鼠标信息网传到另一个系统,接受信息的系统通过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
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值