📄 demo.c
字号:
/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * Copyright (C) 2007, 2010 fengGuojin(fgjnew@163.com) */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/moduleparam.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/slab.h> #include <linux/fs.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/seq_file.h>#include <linux/cdev.h>#include <linux/version.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/ctype.h>#include <linux/sched.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#include <linux/types.h> /* size_t */#include <linux/interrupt.h> /* mark_bh */#include <linux/in.h>#include <linux/netdevice.h> /* struct device, and other headers */#include <linux/etherdevice.h> /* eth_type_trans */#include <linux/ip.h> /* struct iphdr */#include <linux/tcp.h> /* struct tcphdr */#include <linux/skbuff.h>#include <linux/in6.h>#include <asm/checksum.h>#include "demo.h"MODULE_AUTHOR("fgj");MODULE_LICENSE("Dual BSD/GPL");int demo_open(struct net_device *dev){ memcpy(dev->dev_addr, "\0ED000", ETH_ALEN); netif_start_queue(dev); return 0;}int demo_release(struct net_device *dev){ netif_stop_queue(dev); return 0;}int demo_config(struct net_device *dev, struct ifmap *map){ if (dev->flags & IFF_UP) return -EBUSY; /* change the io_base addr */ if (map->base_addr != dev->base_addr) { printk(KERN_WARNING "demo: Can't change I/O address\n"); return -EOPNOTSUPP; } /* can change the irq */ if (map->irq != dev->irq) { dev->irq = map->irq; } return 0;}/* * demo_rx,recieves a network packet and put the packet into TCP/IP up * layer,netif_rx() is the kernel API to do such thing. The recieving * procedure must alloc the sk_buff structure to store the data, * and the sk_buff will be freed in the up layer. */void demo_rx(struct net_device *dev, int len, unsigned char *buf){ struct sk_buff *skb; struct demo_priv *priv = (struct demo_priv *) dev->priv; skb = dev_alloc_skb(len+2); if (!skb) { printk("demo_rx can not allocate more memory to store the packet. drop the packet\n"); priv->stats.rx_dropped++; return; } skb_reserve(skb, 2); memcpy(skb_put(skb, len), buf, len); skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); /* We need not check the checksum */ skb->ip_summed = CHECKSUM_UNNECESSARY; priv->stats.rx_packets++; netif_rx(skb); return;}/* * pseudo network hareware transmit,it just put the data into the * ed_tx device. */void demo_hw_tx(char *buf, int len, struct net_device *dev){ struct demo_priv *priv; /* check the ip packet length,it must more then 34 octets */ if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) { printk("Bad packet! It's size is less then 34!\n"); return; } printk("%s\n",buf); /* record the transmitted packet status */ priv = (struct demo_priv *) dev->priv; priv->stats.tx_packets++; priv->stats.rx_bytes += len; /* remember to free the sk_buffer allocated in upper layer. */ dev_kfree_skb(priv->skb);}/* * Transmit the packet,called by the kernel when there is an * application wants to transmit a packet. */int demo_tx(struct sk_buff *skb, struct net_device *dev){ int len; char *data; struct demo_priv *priv = (struct demo_priv *) dev->priv; len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; data = skb->data; /* stamp the time stamp */ dev->trans_start = jiffies; /* remember the skb and free it in demo_hw_tx */ priv->skb = skb; /* pseudo transmit the packet,hehe */ demo_hw_tx(data, len, dev); return 0; }/* * Deal with a transmit timeout. */void demo_tx_timeout (struct net_device *dev){ struct demo_priv *priv = (struct demo_priv *) dev->priv; priv->stats.tx_errors++; netif_wake_queue(dev); return;}/* * When we need some ioctls. */int demo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){ return 0;}/* * ifconfig to get the packet transmitting status. */struct net_device_stats *demo_stats(struct net_device *dev){ struct demo_priv *priv = (struct demo_priv *) dev->priv; return &priv->stats;}/* * TCP/IP handshake will call this function, if it need. */int demo_change_mtu(struct net_device *dev, int new_mtu){ unsigned long flags; spinlock_t *lock = &((struct demo_priv *) dev->priv)->lock; /* en, the mtu CANNOT LESS THEN 68 OR MORE THEN 1500. */ if (new_mtu < 68) return -EINVAL; spin_lock_irqsave(lock, flags); dev->mtu = new_mtu; spin_unlock_irqrestore(lock, flags); return 0; }int demo_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned int len){ struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN); eth->h_proto = htons(type); memcpy(eth->h_source,saddr? saddr : dev->dev_addr,dev->addr_len); memcpy(eth->h_dest, daddr? daddr : dev->dev_addr, dev->addr_len); return (dev->hard_header_len);}int demo_rebuild_header(struct sk_buff *skb){ struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN); struct net_device *dev = skb->dev; memcpy(eth->h_source, dev->dev_addr ,dev->addr_len); memcpy(eth->h_dest, dev->dev_addr , dev->addr_len); return 0;}void demo_init(struct net_device *dev){ struct demo_priv *priv; ether_setup(dev); /* assign some of the fields */ dev->open = demo_open; dev->stop = demo_release; dev->set_config = demo_config; dev->hard_start_xmit = demo_tx; dev->do_ioctl = demo_ioctl; dev->get_stats = demo_stats; dev->change_mtu = demo_change_mtu; dev->rebuild_header = demo_rebuild_header; dev->hard_header = demo_header; dev->tx_timeout = demo_tx_timeout; /* keep the default flags, just add NOARP */ dev->flags |= IFF_NOARP; dev->features |= NETIF_F_NO_CSUM; dev->hard_header_cache = NULL; /* Disable caching */ /* * Then, initialize the priv field. This encloses the statistics * and a few private fields. */ priv = netdev_priv(dev); memset(priv, 0, sizeof(struct demo_priv)); spin_lock_init(&priv->lock);}struct net_device *demo_devs;void demo_cleanup(void){ if (demo_devs) { unregister_netdev(demo_devs); free_netdev(demo_devs); } return;}int demo_init_module(void){ int result,ret = -ENOMEM; /* Allocate the devices */ demo_devs=alloc_netdev(sizeof(struct demo_priv), "fgj%d", demo_init); if (demo_devs == NULL) goto out; ret = -ENODEV; if ((result = register_netdev(demo_devs))) printk("demo: error %i registering device \"%s\"\n",result, demo_devs->name); else ret = 0; out: if (ret) demo_cleanup(); return ret;}module_init(demo_init_module);module_exit(demo_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -