dummy.c 3.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/* dummy.c: a dummy net driver

	The purpose of this driver is to provide a device to point a
	route through, but not to actually transmit packets.

	Why?  If you have a machine whose only connection is an occasional
	PPP/SLIP/PLIP link, you can only connect to your own hostname
	when the link is up.  Otherwise you have to use localhost.
	This isn't very consistent.

	One solution is to set up a dummy link using PPP/SLIP/PLIP,
	but this seems (to me) too much overhead for too little gain.
	This driver provides a small alternative. Thus you can do
14

L
Linus Torvalds 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
	[when not running slip]
		ifconfig dummy slip.addr.ess.here up
	[to go to slip]
		ifconfig dummy down
		dip whatever

	This was written by looking at Donald Becker's skeleton driver
	and the loopback driver.  I then threw away anything that didn't
	apply!	Thanks to Alan Cox for the key clue on what to do with
	misguided packets.

			Nick Holloway, 27th May 1994
	[I tweaked this explanation a little but that's all]
			Alan Cox, 30th May 1994
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
37
#include <linux/rtnetlink.h>
38
#include <net/rtnetlink.h>
39

L
Linus Torvalds 已提交
40 41 42 43 44 45 46 47
static int numdummies = 1;

static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);

static int dummy_set_address(struct net_device *dev, void *p)
{
	struct sockaddr *sa = p;

48
	if (!is_valid_ether_addr(sa->sa_data))
L
Linus Torvalds 已提交
49
		return -EADDRNOTAVAIL;
50

L
Linus Torvalds 已提交
51 52 53 54 55 56 57 58 59
	memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
	return 0;
}

/* fake multicast ability */
static void set_multicast_list(struct net_device *dev)
{
}

60
static void dummy_setup(struct net_device *dev)
L
Linus Torvalds 已提交
61 62 63 64 65
{
	/* Initialize the device structure. */
	dev->hard_start_xmit = dummy_xmit;
	dev->set_multicast_list = set_multicast_list;
	dev->set_mac_address = dummy_set_address;
66
	dev->destructor = free_netdev;
L
Linus Torvalds 已提交
67 68 69 70 71 72 73 74 75 76 77 78

	/* Fill in device structure with ethernet-generic values. */
	ether_setup(dev);
	dev->tx_queue_len = 0;
	dev->change_mtu = NULL;
	dev->flags |= IFF_NOARP;
	dev->flags &= ~IFF_MULTICAST;
	random_ether_addr(dev->dev_addr);
}

static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
{
P
Patrick McHardy 已提交
79 80
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;
L
Linus Torvalds 已提交
81 82 83 84 85

	dev_kfree_skb(skb);
	return 0;
}

86 87 88 89 90 91 92 93 94 95 96
static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
{
	if (tb[IFLA_ADDRESS]) {
		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
			return -EINVAL;
		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
			return -EADDRNOTAVAIL;
	}
	return 0;
}

97 98 99
static struct rtnl_link_ops dummy_link_ops __read_mostly = {
	.kind		= "dummy",
	.setup		= dummy_setup,
100
	.validate	= dummy_validate,
101 102
};

L
Linus Torvalds 已提交
103 104 105 106
/* Number of dummy devices to be set up by this module. */
module_param(numdummies, int, 0);
MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");

107
static int __init dummy_init_one(void)
L
Linus Torvalds 已提交
108 109 110 111
{
	struct net_device *dev_dummy;
	int err;

112
	dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
L
Linus Torvalds 已提交
113 114 115
	if (!dev_dummy)
		return -ENOMEM;

116 117 118
	err = dev_alloc_name(dev_dummy, dev_dummy->name);
	if (err < 0)
		goto err;
L
Linus Torvalds 已提交
119

120 121 122 123 124
	dev_dummy->rtnl_link_ops = &dummy_link_ops;
	err = register_netdevice(dev_dummy);
	if (err < 0)
		goto err;
	return 0;
125

126 127 128
err:
	free_netdev(dev_dummy);
	return err;
129
}
L
Linus Torvalds 已提交
130 131

static int __init dummy_init_module(void)
132
{
L
Linus Torvalds 已提交
133
	int i, err = 0;
134

135 136 137
	rtnl_lock();
	err = __rtnl_link_register(&dummy_link_ops);

L
Linus Torvalds 已提交
138
	for (i = 0; i < numdummies && !err; i++)
139
		err = dummy_init_one();
140
	if (err < 0)
141 142 143
		__rtnl_link_unregister(&dummy_link_ops);
	rtnl_unlock();

L
Linus Torvalds 已提交
144
	return err;
145
}
L
Linus Torvalds 已提交
146 147 148

static void __exit dummy_cleanup_module(void)
{
149
	rtnl_link_unregister(&dummy_link_ops);
L
Linus Torvalds 已提交
150 151 152 153 154
}

module_init(dummy_init_module);
module_exit(dummy_cleanup_module);
MODULE_LICENSE("GPL");
155
MODULE_ALIAS_RTNL_LINK("dummy");
反馈
建议
客服 返回
顶部